diff --git a/BUILD.bazel b/BUILD.bazel index ac91e68acde6..36dd531b3295 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -586,6 +586,7 @@ _ROCKPI4_MODULE_OUTS = [ "drivers/char/hw_random/virtio-rng.ko", "drivers/clk/clk-rk808.ko", "drivers/cpufreq/cpufreq-dt.ko", + "drivers/cpufreq/tegra20-cpufreq.ko", "drivers/dma/pl330.ko", "drivers/gpu/drm/bridge/analogix/analogix_dp.ko", "drivers/gpu/drm/bridge/synopsys/dw-hdmi.ko", diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 257ae753f030..4413ebbb7289 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -5383,6 +5383,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x1d6740b1 } +pointer_reference { + id: 0x0dca21d4 + kind: POINTER + pointee_type_id: 0x1d6861ce +} pointer_reference { id: 0x0dcbeae6 kind: POINTER @@ -10548,6 +10553,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x58912da5 } +pointer_reference { + id: 0x1cba6ba2 + kind: POINTER + pointee_type_id: 0x58a94817 +} pointer_reference { id: 0x1cc18442 kind: POINTER @@ -20048,6 +20058,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x906c53c0 } +pointer_reference { + id: 0x2e8c0d7b + kind: POINTER + pointee_type_id: 0x9070d372 +} pointer_reference { id: 0x2e8c7bd9 kind: POINTER @@ -20068,6 +20083,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x9078a69f } +pointer_reference { + id: 0x2e8e5582 + kind: POINTER + pointee_type_id: 0x9079b097 +} pointer_reference { id: 0x2e8ed696 kind: POINTER @@ -20258,6 +20278,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0x9095e0a9 } +pointer_reference { + id: 0x2eb6a848 + kind: POINTER + pointee_type_id: 0x909a47bd +} pointer_reference { id: 0x2eb6ced9 kind: POINTER @@ -23593,6 +23618,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xe32fa2b6 } +pointer_reference { + id: 0x32618dc6 + kind: POINTER + pointee_type_id: 0xe3c6d185 +} pointer_reference { id: 0x326663cd kind: POINTER @@ -23738,6 +23768,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xe08cc03f } +pointer_reference { + id: 0x32b472a5 + kind: POINTER + pointee_type_id: 0xe0912c08 +} pointer_reference { id: 0x32b54b11 kind: POINTER @@ -24443,6 +24478,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xfa0fa371 } +pointer_reference { + id: 0x3417d991 + kind: POINTER + pointee_type_id: 0xfa1f80d8 +} pointer_reference { id: 0x34192ccc kind: POINTER @@ -24713,6 +24753,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf87d4486 } +pointer_reference { + id: 0x348f7ef2 + kind: POINTER + pointee_type_id: 0xf87d1d57 +} pointer_reference { id: 0x348f9528 kind: POINTER @@ -25543,6 +25588,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf34f7202 } +pointer_reference { + id: 0x364a10f4 + kind: POINTER + pointee_type_id: 0xf368a54d +} pointer_reference { id: 0x364efcf0 kind: POINTER @@ -25608,6 +25658,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf39c3f1e } +pointer_reference { + id: 0x367f8642 + kind: POINTER + pointee_type_id: 0xf3beff96 +} pointer_reference { id: 0x36841126 kind: POINTER @@ -26238,6 +26293,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xf4a306a1 } +pointer_reference { + id: 0x37c0c175 + kind: POINTER + pointee_type_id: 0xf543e34b +} pointer_reference { id: 0x37c1fe6c kind: POINTER @@ -26443,6 +26503,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xca7029d8 } +pointer_reference { + id: 0x3812c788 + kind: POINTER + pointee_type_id: 0xca0bf8bc +} pointer_reference { id: 0x381472e2 kind: POINTER @@ -26793,6 +26858,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xc94d23ab } +pointer_reference { + id: 0x38c3d772 + kind: POINTER + pointee_type_id: 0xc94fbb56 +} pointer_reference { id: 0x38c5be1f kind: POINTER @@ -27573,6 +27643,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xc035887a } +pointer_reference { + id: 0x3aa533cf + kind: POINTER + pointee_type_id: 0xc0d429a1 +} pointer_reference { id: 0x3aac87ab kind: POINTER @@ -28533,6 +28608,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd920878f } +pointer_reference { + id: 0x3cdda08b + kind: POINTER + pointee_type_id: 0xd93664b2 +} pointer_reference { id: 0x3ce1bbd3 kind: POINTER @@ -29098,6 +29178,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd23047c9 } +pointer_reference { + id: 0x3e21070b + kind: POINTER + pointee_type_id: 0xd2c4fab2 +} pointer_reference { id: 0x3e279e0a kind: POINTER @@ -29478,6 +29563,11 @@ pointer_reference { kind: POINTER pointee_type_id: 0xd66432be } +pointer_reference { + id: 0x3f09383b + kind: POINTER + pointee_type_id: 0xd6640671 +} pointer_reference { id: 0x3f095459 kind: POINTER @@ -32238,6 +32328,11 @@ qualified { qualifier: CONST qualified_type_id: 0x72ec8660 } +qualified { + id: 0xc0d429a1 + qualifier: CONST + qualified_type_id: 0x7317100c +} qualified { id: 0xc12aa3e6 qualifier: CONST @@ -32658,6 +32753,11 @@ qualified { qualifier: CONST qualified_type_id: 0x55733825 } +qualified { + id: 0xc94fbb56 + qualifier: CONST + qualified_type_id: 0x55795bd3 +} qualified { id: 0xc97bedb7 qualifier: CONST @@ -32673,6 +32773,11 @@ qualified { qualifier: CONST qualified_type_id: 0x5786c646 } +qualified { + id: 0xca0bf8bc + qualifier: CONST + qualified_type_id: 0x58685478 +} qualified { id: 0xca2c0eb3 qualifier: CONST @@ -33208,6 +33313,11 @@ qualified { qualifier: CONST qualified_type_id: 0x399c459b } +qualified { + id: 0xd2c4fab2 + qualifier: CONST + qualified_type_id: 0x3b545c43 +} qualified { id: 0xd2d7132a qualifier: CONST @@ -33368,6 +33478,11 @@ qualified { qualifier: CONST qualified_type_id: 0x29600806 } +qualified { + id: 0xd6640671 + qualifier: CONST + qualified_type_id: 0x29d7af4d +} qualified { id: 0xd66432be qualifier: CONST @@ -33518,6 +33633,11 @@ qualified { qualifier: CONST qualified_type_id: 0x13b5a562 } +qualified { + id: 0xd93664b2 + qualifier: CONST + qualified_type_id: 0x149e2442 +} qualified { id: 0xd957a3fb qualifier: CONST @@ -33978,6 +34098,11 @@ qualified { qualifier: CONST qualified_type_id: 0xf274b676 } +qualified { + id: 0xe0912c08 + qualifier: CONST + qualified_type_id: 0xf20306a8 +} qualified { id: 0xe095cad8 qualifier: CONST @@ -34978,6 +35103,11 @@ qualified { qualifier: CONST qualified_type_id: 0xbd7a7e80 } +qualified { + id: 0xf368a54d + qualifier: CONST + qualified_type_id: 0xbde523bd +} qualified { id: 0xf39072f0 qualifier: CONST @@ -35243,6 +35373,11 @@ qualified { qualifier: CONST qualified_type_id: 0x91b5a647 } +qualified { + id: 0xf87d1d57 + qualifier: CONST + qualified_type_id: 0x91b3c3d5 +} qualified { id: 0xf87f5460 qualifier: CONST @@ -40461,6 +40596,11 @@ member { type_id: 0x56037e9c offset: 1408 } +member { + id: 0x36707bb7 + type_id: 0x56efb9c6 + offset: 128 +} member { id: 0x36752018 type_id: 0x56faddc1 @@ -45484,6 +45624,12 @@ member { type_id: 0x2dd03fae offset: 320 } +member { + id: 0xd7bdfbb1 + name: "aggregate" + type_id: 0x2dd03fae + offset: 64 +} member { id: 0x9b642e7a name: "ah_ip4_spec" @@ -50407,6 +50553,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0xd3de74cf + name: "atom_size" + type_id: 0x4585663f + offset: 256 +} member { id: 0x176dead7 name: "atomic" @@ -53379,6 +53531,12 @@ member { type_id: 0xe04f9dc7 offset: 704 } +member { + id: 0xbc613338 + name: "bcast_ch_regs" + type_id: 0x18bd6530 + offset: 256 +} member { id: 0x638c2bea name: "bcdCDC" @@ -54427,6 +54585,18 @@ member { type_id: 0x295c7202 offset: 40 } +member { + id: 0x13de4517 + name: "bit" + type_id: 0x4585663f + offset: 224 +} +member { + id: 0x13de4b08 + name: "bit" + type_id: 0x4585663f + offset: 32 +} member { id: 0xdd1aee2e name: "bit_count" @@ -55004,6 +55174,12 @@ member { type_id: 0xe8034002 offset: 13456 } +member { + id: 0x9728511c + name: "block_dma" + type_id: 0x2eb6a848 + offset: 128 +} member { id: 0xecca238a name: "block_h" @@ -60665,6 +60841,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0x20f935a9 + name: "ch_intmask" + type_id: 0xc9082b19 + offset: 416 +} member { id: 0x2054ca12 name: "ch_mode" @@ -60677,6 +60859,12 @@ member { type_id: 0xe62ebf07 offset: 64 } +member { + id: 0x46f26d43 + name: "ch_regs" + type_id: 0x0cbf60eb + offset: 320 +} member { id: 0x152992ef name: "chain" @@ -62696,6 +62884,12 @@ member { type_id: 0x18bd6530 offset: 3456 } +member { + id: 0x685f31a0 + name: "client_id_mask" + type_id: 0x914dbfdc + offset: 288 +} member { id: 0xf4c5928f name: "client_list" @@ -62720,6 +62914,11 @@ member { type_id: 0xa7c362b0 offset: 2432 } +member { + id: 0x1b57faed + name: "clients" + type_id: 0x38c3d772 +} member { id: 0x1bbcf6b9 name: "clients" @@ -62779,6 +62978,12 @@ member { name: "clk" type_id: 0x3dcee85d } +member { + id: 0xc8e82903 + name: "clk" + type_id: 0x3dcee85d + offset: 384 +} member { id: 0xc8e82c70 name: "clk" @@ -66636,6 +66841,12 @@ member { type_id: 0x0baa70a7 offset: 96 } +member { + id: 0xfc79e947 + name: "control" + type_id: 0x4585663f + offset: 128 +} member { id: 0xfcf56dc8 name: "control" @@ -72778,6 +72989,12 @@ member { type_id: 0x03913382 offset: 62528 } +member { + id: 0x1c1be12d + name: "debugfs" + type_id: 0x3c9f0fa2 + offset: 2368 +} member { id: 0x1c35735f name: "debugfs" @@ -73125,6 +73342,12 @@ member { type_id: 0x4585663f offset: 32 } +member { + id: 0xea7685d3 + name: "def" + type_id: 0x4585663f + offset: 96 +} member { id: 0xffdeb7b9 name: "def_br_lsto" @@ -78953,6 +79176,12 @@ member { type_id: 0xf435685e offset: 19264 } +member { + id: 0x4c6d670f + name: "dma_idling" + type_id: 0x367f8642 + offset: 192 +} member { id: 0xf4c016ce name: "dma_io_tlb_mem" @@ -82950,6 +83179,18 @@ member { type_id: 0x295c7202 offset: 11912 } +member { + id: 0x321ff48e + name: "emem_data" + type_id: 0x38d23361 + offset: 64 +} +member { + id: 0x4ffc68c3 + name: "emem_regs" + type_id: 0x3ea31487 + offset: 128 +} member { id: 0xfcf1c4f6 name: "emin" @@ -89810,6 +90051,12 @@ member { type_id: 0x0e5445cf offset: 640 } +member { + id: 0xf67ca58b + name: "fifo_size" + type_id: 0x4585663f + offset: 160 +} member { id: 0xf67ca8c0 name: "fifo_size" @@ -96167,6 +96414,12 @@ member { type_id: 0x295c7202 offset: 1080 } +member { + id: 0xf5682334 + name: "gart" + type_id: 0x1cba6ba2 + offset: 128 +} member { id: 0x16b7aef5 name: "gate" @@ -98584,6 +98837,12 @@ member { type_id: 0x49a73111 offset: 2304 } +member { + id: 0x7fbcccea + name: "global_intstatus_channel_shift" + type_id: 0xc9082b19 + offset: 448 +} member { id: 0x88f8622b name: "global_l" @@ -99290,6 +99549,12 @@ member { type_id: 0x3776a166 offset: 128 } +member { + id: 0x933b8dad + name: "groups" + type_id: 0x3cdda08b + offset: 256 +} member { id: 0x9342d5c0 name: "groups" @@ -99721,6 +99986,12 @@ member { type_id: 0x2dfb782b offset: 960 } +member { + id: 0x72a70f4f + name: "handle_irq" + type_id: 0x044ba8c8 + offset: 256 +} member { id: 0x33f92e8a name: "handle_kick" @@ -99998,6 +100269,12 @@ member { type_id: 0x2c494e22 offset: 192 } +member { + id: 0x3ec0be10 + name: "has_addr_hi_reg" + type_id: 0x6d7f5ff6 + offset: 480 +} member { id: 0xeee91e70 name: "has_alpha" @@ -102686,6 +102963,17 @@ member { type_id: 0xdba44af3 offset: 26944 } +member { + id: 0x2ff7d481 + name: "hotreset_assert" + type_id: 0x2eb6a848 +} +member { + id: 0xb245cfae + name: "hotreset_deassert" + type_id: 0x2eb6a848 + offset: 64 +} member { id: 0x354661e5 name: "hour" @@ -104620,6 +104908,12 @@ member { offset: 416 bitsize: 1 } +member { + id: 0x0c93d7b1 + name: "icc_ops" + type_id: 0x3e21070b + offset: 704 +} member { id: 0x9dfcef2c name: "icc_paths" @@ -105072,6 +105366,12 @@ member { type_id: 0x37145079 offset: 1608 } +member { + id: 0xcc1c5d14 + name: "id" + type_id: 0x33756485 + offset: 64 +} member { id: 0xcc248bda name: "id" @@ -110149,6 +110449,12 @@ member { type_id: 0x3ae3ff84 offset: 1088 } +member { + id: 0x1b9b6526 + name: "intmask" + type_id: 0xc9082b19 + offset: 384 +} member { id: 0x5dfd62b5 name: "intr_cmd" @@ -111810,6 +112116,12 @@ member { type_id: 0x6720d32f offset: 320 } +member { + id: 0x99159291 + name: "irq" + type_id: 0x6720d32f + offset: 448 +} member { id: 0x99159514 name: "irq" @@ -115398,6 +115710,12 @@ member { type_id: 0xb3e7bac9 offset: 296 } +member { + id: 0x1713d000 + name: "la" + type_id: 0x1ba1b239 + offset: 64 +} member { id: 0xbe79d648 name: "la_mask" @@ -119901,6 +120219,12 @@ member { type_id: 0xf313e71a offset: 320 } +member { + id: 0x2d1feb8e + name: "lock" + type_id: 0xf313e71a + offset: 2304 +} member { id: 0x2d1feb9a name: "lock" @@ -139222,6 +139546,12 @@ member { type_id: 0x33756485 offset: 704 } +member { + id: 0x4b9a0804 + name: "num_address_bits" + type_id: 0x4585663f + offset: 224 +} member { id: 0x4b1eeeac name: "num_agents" @@ -139263,6 +139593,12 @@ member { type_id: 0xc9082b19 offset: 128 } +member { + id: 0x29605801 + name: "num_asids" + type_id: 0x4585663f + offset: 416 +} member { id: 0x4a3e96b6 name: "num_auto_selectable_formats" @@ -139376,6 +139712,12 @@ member { type_id: 0x6720d32f offset: 8384 } +member { + id: 0x5fe2c2d5 + name: "num_channels" + type_id: 0x295c7202 + offset: 304 +} member { id: 0xc21eb7ca name: "num_chans" @@ -139400,6 +139742,12 @@ member { type_id: 0x914dbfdc offset: 7440 } +member { + id: 0xe6531f76 + name: "num_clients" + type_id: 0x4585663f + offset: 64 +} member { id: 0x1c9b1176 name: "num_clips" @@ -139638,6 +139986,12 @@ member { type_id: 0x0baa70a7 offset: 64 } +member { + id: 0x8f1bb1bf + name: "num_emem_regs" + type_id: 0x4585663f + offset: 192 +} member { id: 0x4a422b42 name: "num_encoder" @@ -139799,6 +140153,12 @@ member { type_id: 0x4585663f offset: 448 } +member { + id: 0x1eceb58f + name: "num_groups" + type_id: 0x4585663f + offset: 320 +} member { id: 0x0a575aaf name: "num_h_tile" @@ -140448,6 +140808,12 @@ member { type_id: 0x4585663f offset: 384 } +member { + id: 0xfe804b5a + name: "num_resets" + type_id: 0x4585663f + offset: 640 +} member { id: 0xdc465f86 name: "num_resources" @@ -140658,6 +141024,18 @@ member { type_id: 0x4585663f offset: 192 } +member { + id: 0x3a29648c + name: "num_swgroups" + type_id: 0x4585663f + offset: 192 +} +member { + id: 0x3a296587 + name: "num_swgroups" + type_id: 0x4585663f + offset: 128 +} member { id: 0x313aeebb name: "num_syms" @@ -140724,6 +141102,18 @@ member { name: "num_timings" type_id: 0x4585663f } +member { + id: 0x349422f9 + name: "num_timings" + type_id: 0x4585663f + offset: 704 +} +member { + id: 0xb021dbba + name: "num_tlb_lines" + type_id: 0x4585663f + offset: 384 +} member { id: 0x8026d50a name: "num_total_plane" @@ -143550,6 +143940,12 @@ member { name: "ops" type_id: 0x326a19f7 } +member { + id: 0xafb9bc7f + name: "ops" + type_id: 0x32b472a5 + offset: 768 +} member { id: 0xafb9c47f name: "ops" @@ -144793,6 +145189,11 @@ member { type_id: 0x6720d32f offset: 288 } +member { + id: 0xd2c76e4c + name: "override" + type_id: 0x4585663f +} member { id: 0xb4e4bcf1 name: "override_edid" @@ -155810,6 +156211,11 @@ member { type_id: 0x2e7404d6 offset: 128 } +member { + id: 0xd7788f3a + name: "probe" + type_id: 0x2e8c0d7b +} member { id: 0xd778c72d name: "probe" @@ -155965,6 +156371,12 @@ member { type_id: 0x3daf8dd1 offset: 128 } +member { + id: 0xe5f24cd0 + name: "probe_device" + type_id: 0x2e8e5582 + offset: 320 +} member { id: 0xf6b66ca8 name: "probe_finalize" @@ -157289,6 +157701,12 @@ member { type_id: 0x32c23ae3 offset: 256 } +member { + id: 0x86b9fc17 + name: "provider" + type_id: 0xe1480d10 + offset: 1472 +} member { id: 0xa159a1de name: "provider_data" @@ -163364,6 +163782,12 @@ member { type_id: 0x4585663f offset: 128 } +member { + id: 0x0f050edd + name: "reg" + type_id: 0x4585663f + offset: 96 +} member { id: 0x0f27a2eb name: "reg" @@ -164007,12 +164431,24 @@ member { name: "regs" type_id: 0x34def0b7 } +member { + id: 0x8011b26a + name: "regs" + type_id: 0x2accfd18 + offset: 192 +} member { id: 0x8023c171 name: "regs" type_id: 0x18bd6530 offset: 3456 } +member { + id: 0x8023c3f2 + name: "regs" + type_id: 0x18bd6530 + offset: 192 +} member { id: 0x8023cc24 name: "regs" @@ -164979,6 +165415,12 @@ member { name: "remove" type_id: 0x0dd7b940 } +member { + id: 0xb4ae1e7a + name: "remove" + type_id: 0x0dca21d4 + offset: 64 +} member { id: 0xb4ae4933 name: "remove" @@ -167136,6 +167578,12 @@ member { type_id: 0xb3e7bac9 offset: 216 } +member { + id: 0x621c7011 + name: "reset" + type_id: 0xa1d6f6c0 + offset: 768 +} member { id: 0x6290827d name: "reset" @@ -167265,6 +167713,12 @@ member { type_id: 0x6d7f5ff6 offset: 512 } +member { + id: 0x62f823e6 + name: "reset" + type_id: 0x4585663f + offset: 192 +} member { id: 0x147cd330 name: "reset_assert_delay" @@ -167380,6 +167834,12 @@ member { type_id: 0x0d9c4ffe offset: 256 } +member { + id: 0x69014681 + name: "reset_ops" + type_id: 0x364a10f4 + offset: 512 +} member { id: 0x98c83941 name: "reset_pending" @@ -167441,6 +167901,12 @@ member { type_id: 0x2ced3956 offset: 512 } +member { + id: 0x4d689b1d + name: "reset_status" + type_id: 0x2eb6a848 + offset: 320 +} member { id: 0xf24ab676 name: "reset_system" @@ -167477,6 +167943,12 @@ member { type_id: 0x1f3c8679 offset: 7744 } +member { + id: 0x54c3a704 + name: "resets" + type_id: 0x3aa533cf + offset: 576 +} member { id: 0x4381fffc name: "resetting_device" @@ -168036,6 +168508,12 @@ member { type_id: 0x2ee76b64 offset: 2240 } +member { + id: 0xcab164a8 + name: "resume" + type_id: 0x2e8c0d7b + offset: 192 +} member { id: 0xcab17152 name: "resume" @@ -169245,6 +169723,11 @@ member { type_id: 0x120540d1 offset: 640 } +member { + id: 0x93cd2de4 + name: "root" + type_id: 0x120540d1 +} member { id: 0x93d246f9 name: "root" @@ -174917,6 +175400,12 @@ member { type_id: 0x18bd6530 offset: 7680 } +member { + id: 0xf1c9d4d6 + name: "security" + type_id: 0x4585663f + offset: 32 +} member { id: 0xad84e518 name: "security_cfm" @@ -176281,6 +176770,11 @@ member { type_id: 0x2d1b3b77 offset: 256 } +member { + id: 0x3df35bca + name: "set" + type_id: 0x2d1b3b77 +} member { id: 0x8fd22bb3 name: "set_ackreq_default" @@ -179439,12 +179933,23 @@ member { type_id: 0xd3c80119 offset: 64 } +member { + id: 0x081eac68 + name: "sid" + type_id: 0x2ce1ed3d + offset: 192 +} member { id: 0x086ca956 name: "sid" type_id: 0x5eeb4a25 offset: 1472 } +member { + id: 0x0877c02a + name: "sid" + type_id: 0x4585663f +} member { id: 0x08a308f3 name: "sid" @@ -182014,6 +182519,23 @@ member { type_id: 0x2e0f9112 offset: 384 } +member { + id: 0xca95fcc2 + name: "smmu" + type_id: 0x1ba9f29e +} +member { + id: 0xcab15bcf + name: "smmu" + type_id: 0x3f09383b + offset: 320 +} +member { + id: 0xcabc305c + name: "smmu" + type_id: 0x32618dc6 + offset: 64 +} member { id: 0x0c1eb745 name: "smp" @@ -182273,6 +182795,12 @@ member { type_id: 0xe62ebf07 offset: 32 } +member { + id: 0xb0492744 + name: "soc" + type_id: 0x348f7ef2 + offset: 512 +} member { id: 0x3de92190 name: "soc_dev_num" @@ -186146,6 +186674,12 @@ member { type_id: 0x4585663f offset: 1248 } +member { + id: 0x2022af02 + name: "status" + type_id: 0x4585663f + offset: 160 +} member { id: 0x2027a418 name: "status" @@ -188171,6 +188705,12 @@ member { type_id: 0x3500e23a offset: 64 } +member { + id: 0x009679b8 + name: "supports_request_limit" + type_id: 0x6d7f5ff6 + offset: 360 +} member { id: 0x065dd0db name: "supports_requests" @@ -188178,6 +188718,12 @@ member { offset: 197 bitsize: 1 } +member { + id: 0xe739cbf3 + name: "supports_round_robin_arbitration" + type_id: 0x6d7f5ff6 + offset: 352 +} member { id: 0x505b26be name: "suppress" @@ -188256,6 +188802,12 @@ member { type_id: 0x2e9195ef offset: 192 } +member { + id: 0xf39453f6 + name: "suspend" + type_id: 0x2e8c0d7b + offset: 128 +} member { id: 0xf394d5ee name: "suspend" @@ -188940,6 +189492,29 @@ member { type_id: 0xb914bfab offset: 1600 } +member { + id: 0x005de33e + name: "swgroup" + type_id: 0x4585663f + offset: 64 +} +member { + id: 0x005de7df + name: "swgroup" + type_id: 0x4585663f +} +member { + id: 0x3f043e5d + name: "swgroups" + type_id: 0x3812c788 + offset: 128 +} +member { + id: 0x3f05edad + name: "swgroups" + type_id: 0x39cc14ac + offset: 64 +} member { id: 0x0bc9608d name: "switch_id" @@ -193028,6 +193603,12 @@ member { type_id: 0x3df0a7d3 offset: 128 } +member { + id: 0xe87350be + name: "tick" + type_id: 0x33756485 + offset: 576 +} member { id: 0xe879699b name: "tick" @@ -193953,6 +194534,12 @@ member { type_id: 0x3ebb35fd offset: 1280 } +member { + id: 0x1f6d9836 + name: "timings" + type_id: 0x3417d991 + offset: 640 +} member { id: 0x1fa42388 name: "timings" @@ -200656,6 +201243,12 @@ member { type_id: 0x0eb62dc3 offset: 320 } +member { + id: 0xea5b0b9a + name: "unblock_dma" + type_id: 0x2eb6a848 + offset: 256 +} member { id: 0x5c7ec059 name: "unbound_attrs" @@ -210782,6 +211375,12 @@ member { type_id: 0x01d9df85 offset: 576 } +member { + id: 0x0b59f1cd + name: "xlate_extended" + type_id: 0x01d9df85 + offset: 128 +} member { id: 0xee360321 name: "xlate_tdm_slot_mask" @@ -213428,6 +214027,26 @@ struct_union { member_id: 0xf5eb6708 } } +struct_union { + id: 0x1ba1b239 + kind: STRUCT + definition { + bytesize: 16 + member_id: 0x0f05075e + member_id: 0x3274483b + member_id: 0xa876e8aa + member_id: 0xea7685d3 + } +} +struct_union { + id: 0x1ba9f29e + kind: STRUCT + definition { + bytesize: 8 + member_id: 0x0f05075e + member_id: 0x13de4b08 + } +} struct_union { id: 0x1c07f73e kind: STRUCT @@ -214095,6 +214714,16 @@ struct_union { member_id: 0x642f0821 } } +struct_union { + id: 0x2accfd18 + kind: STRUCT + definition { + bytesize: 32 + member_id: 0xca95fcc2 + member_id: 0x1713d000 + member_id: 0x081eac68 + } +} struct_union { id: 0x2b189f72 kind: STRUCT @@ -214206,6 +214835,15 @@ struct_union { member_id: 0x3e7e5067 } } +struct_union { + id: 0x2ce1ed3d + kind: STRUCT + definition { + bytesize: 8 + member_id: 0xd2c76e4c + member_id: 0xf1c9d4d6 + } +} struct_union { id: 0x2d07e8c3 kind: STRUCT @@ -215041,6 +215679,14 @@ struct_union { member_id: 0xc101e64f } } +struct_union { + id: 0x3c9f0fa2 + kind: STRUCT + definition { + bytesize: 8 + member_id: 0x93cd2de4 + } +} struct_union { id: 0x3ce2dc79 kind: STRUCT @@ -216369,6 +217015,15 @@ struct_union { member_id: 0x4380fca4 } } +struct_union { + id: 0x56efb9c6 + kind: UNION + definition { + bytesize: 4 + member_id: 0x005de7df + member_id: 0x0877c02a + } +} struct_union { id: 0x56faddc1 kind: UNION @@ -234643,6 +235298,11 @@ struct_union { member_id: 0x34fb052c } } +struct_union { + id: 0x58a94817 + kind: STRUCT + name: "gart_device" +} struct_union { id: 0x78ef929d kind: STRUCT @@ -262965,6 +263625,177 @@ struct_union { member_id: 0x08c59955 } } +struct_union { + id: 0xf543e34b + kind: STRUCT + name: "tegra_mc" + definition { + bytesize: 304 + member_id: 0xce3bbab3 + member_id: 0xcabc305c + member_id: 0xf5682334 + member_id: 0x8023c3f2 + member_id: 0xbc613338 + member_id: 0x46f26d43 + member_id: 0xc8e82903 + member_id: 0x99159291 + member_id: 0xb0492744 + member_id: 0xe87350be + member_id: 0x1f6d9836 + member_id: 0x349422f9 + member_id: 0x621c7011 + member_id: 0x86b9fc17 + member_id: 0x2d1feb8e + member_id: 0x1c1be12d + } +} +struct_union { + id: 0x55795bd3 + kind: STRUCT + name: "tegra_mc_client" + definition { + bytesize: 56 + member_id: 0xcc6aa9f7 + member_id: 0x0de57809 + member_id: 0x36707bb7 + member_id: 0xf67ca58b + member_id: 0x8011b26a + } +} +struct_union { + id: 0x3b545c43 + kind: STRUCT + name: "tegra_mc_icc_ops" + definition { + bytesize: 24 + member_id: 0x3df35bca + member_id: 0xd7bdfbb1 + member_id: 0x0b59f1cd + } +} +struct_union { + id: 0xf20306a8 + kind: STRUCT + name: "tegra_mc_ops" + definition { + bytesize: 48 + member_id: 0xd7788f3a + member_id: 0xb4ae1e7a + member_id: 0xf39453f6 + member_id: 0xcab164a8 + member_id: 0x72a70f4f + member_id: 0xe5f24cd0 + } +} +struct_union { + id: 0x7317100c + kind: STRUCT + name: "tegra_mc_reset" + definition { + bytesize: 32 + member_id: 0x0de57ce8 + member_id: 0xcc1c5d14 + member_id: 0xfc79e947 + member_id: 0x2022af02 + member_id: 0x62f823e6 + member_id: 0x13de4517 + } +} +struct_union { + id: 0xbde523bd + kind: STRUCT + name: "tegra_mc_reset_ops" + definition { + bytesize: 48 + member_id: 0x2ff7d481 + member_id: 0xb245cfae + member_id: 0x9728511c + member_id: 0x4c6d670f + member_id: 0xea5b0b9a + member_id: 0x4d689b1d + } +} +struct_union { + id: 0x91b3c3d5 + kind: STRUCT + name: "tegra_mc_soc" + definition { + bytesize: 104 + member_id: 0x1b57faed + member_id: 0xe6531f76 + member_id: 0x4ffc68c3 + member_id: 0x8f1bb1bf + member_id: 0x4b9a0804 + member_id: 0xd3de74cf + member_id: 0x685f31a0 + member_id: 0x5fe2c2d5 + member_id: 0xcab15bcf + member_id: 0x1b9b6526 + member_id: 0x20f935a9 + member_id: 0x7fbcccea + member_id: 0x3ec0be10 + member_id: 0x69014681 + member_id: 0x54c3a704 + member_id: 0xfe804b5a + member_id: 0x0c93d7b1 + member_id: 0xafb9bc7f + } +} +struct_union { + id: 0xfa1f80d8 + kind: STRUCT + name: "tegra_mc_timing" + definition { + bytesize: 16 + member_id: 0x5fe1279a + member_id: 0x321ff48e + } +} +struct_union { + id: 0xe3c6d185 + kind: STRUCT + name: "tegra_smmu" +} +struct_union { + id: 0x149e2442 + kind: STRUCT + name: "tegra_smmu_group_soc" + definition { + bytesize: 24 + member_id: 0x0de57ce8 + member_id: 0x3f05edad + member_id: 0x3a296587 + } +} +struct_union { + id: 0x29d7af4d + kind: STRUCT + name: "tegra_smmu_soc" + definition { + bytesize: 56 + member_id: 0x1b57faed + member_id: 0xe6531f76 + member_id: 0x3f043e5d + member_id: 0x3a29648c + member_id: 0x933b8dad + member_id: 0x1eceb58f + member_id: 0xe739cbf3 + member_id: 0x009679b8 + member_id: 0xb021dbba + member_id: 0x29605801 + } +} +struct_union { + id: 0x58685478 + kind: STRUCT + name: "tegra_smmu_swgroup" + definition { + bytesize: 16 + member_id: 0x0de57ce8 + member_id: 0x005de33e + member_id: 0x0f050edd + } +} struct_union { id: 0x6a268aa0 kind: STRUCT @@ -301352,6 +302183,11 @@ function { parameter_id: 0x1d44326e parameter_id: 0xf1a6dfed } +function { + id: 0x1d6861ce + return_type_id: 0x48b5725f + parameter_id: 0x37c0c175 +} function { id: 0x1d6aeee7 return_type_id: 0x48b5725f @@ -303680,6 +304516,11 @@ function { parameter_id: 0xfc0e1dbd parameter_id: 0x01222f7d } +function { + id: 0x2195423c + return_type_id: 0x37c0c175 + parameter_id: 0x0258f96e +} function { id: 0x21a7fa19 return_type_id: 0x145f7b00 @@ -310228,6 +311069,11 @@ function { parameter_id: 0x36337082 parameter_id: 0x18bd6530 } +function { + id: 0x9070d372 + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 +} function { id: 0x907109f8 return_type_id: 0x6720d32f @@ -310291,6 +311137,12 @@ function { parameter_id: 0x3aff5796 parameter_id: 0x0258f96e } +function { + id: 0x9079b097 + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 + parameter_id: 0x0258f96e +} function { id: 0x908495c3 return_type_id: 0x6720d32f @@ -310379,6 +311231,11 @@ function { parameter_id: 0x4585663f parameter_id: 0x3e10b518 } +function { + id: 0x90953240 + return_type_id: 0x6720d32f + parameter_id: 0x345745bd +} function { id: 0x9095ed8c return_type_id: 0x6720d32f @@ -310416,6 +311273,12 @@ function { parameter_id: 0xe8034002 parameter_id: 0xe8034002 } +function { + id: 0x909a47bd + return_type_id: 0x6720d32f + parameter_id: 0x37c0c175 + parameter_id: 0x3aa533cf +} function { id: 0x909bddf8 return_type_id: 0x6720d32f @@ -336631,6 +337494,12 @@ function { return_type_id: 0x6d7f5ff6 parameter_id: 0x347303b4 } +function { + id: 0xf3beff96 + return_type_id: 0x6d7f5ff6 + parameter_id: 0x37c0c175 + parameter_id: 0x3aa533cf +} function { id: 0xf3c9c4ce return_type_id: 0xeb0f6de6 @@ -351913,6 +352782,15 @@ elf_symbol { type_id: 0x9312d42a full_name: "bitmap_parse" } +elf_symbol { + id: 0xba7da88a + name: "bitmap_parse_user" + is_defined: true + symbol_type: FUNCTION + crc: 0x9a5a8914 + type_id: 0x9312d42a + full_name: "bitmap_parse_user" +} elf_symbol { id: 0x10425c32 name: "bitmap_parselist" @@ -361004,6 +361882,15 @@ elf_symbol { type_id: 0x9d15ab3e full_name: "devm_spi_register_controller" } +elf_symbol { + id: 0x43a4025b + name: "devm_tegra_memory_controller_get" + is_defined: true + symbol_type: FUNCTION + crc: 0x986b8e36 + type_id: 0x2195423c + full_name: "devm_tegra_memory_controller_get" +} elf_symbol { id: 0x0dd13028 name: "devm_thermal_of_cooling_device_register" @@ -398768,6 +399655,15 @@ elf_symbol { type_id: 0x129c1f38 full_name: "tcpm_vbus_change" } +elf_symbol { + id: 0xa8f0fe44 + name: "tegra_mc_probe_device" + is_defined: true + symbol_type: FUNCTION + crc: 0x3f100eaf + type_id: 0x9079b097 + full_name: "tegra_mc_probe_device" +} elf_symbol { id: 0x7cfd9233 name: "teo_cpu_get_util_threshold" @@ -402215,6 +403111,15 @@ elf_symbol { type_id: 0x10985193 full_name: "usb_amd_quirk_pll_enable" } +elf_symbol { + id: 0x406267f4 + name: "usb_anchor_empty" + is_defined: true + symbol_type: FUNCTION + crc: 0x7e8d8619 + type_id: 0x90953240 + full_name: "usb_anchor_empty" +} elf_symbol { id: 0x73c499cf name: "usb_anchor_urb" @@ -402494,6 +403399,15 @@ elf_symbol { type_id: 0x1c1deea6 full_name: "usb_device_match_id" } +elf_symbol { + id: 0xeedbb4b8 + name: "usb_disable_autosuspend" + is_defined: true + symbol_type: FUNCTION + crc: 0xda80b80f + type_id: 0x13c76860 + full_name: "usb_disable_autosuspend" +} elf_symbol { id: 0xdefa9d60 name: "usb_disabled" @@ -403439,6 +404353,15 @@ elf_symbol { type_id: 0x9edfdadc full_name: "usb_reset_device" } +elf_symbol { + id: 0x80c1324b + name: "usb_reset_endpoint" + is_defined: true + symbol_type: FUNCTION + crc: 0x3e614434 + type_id: 0x12d17df8 + full_name: "usb_reset_endpoint" +} elf_symbol { id: 0xb61e8892 name: "usb_role_string" @@ -410026,6 +410949,7 @@ interface { symbol_id: 0xe4dd862f symbol_id: 0x3a1cd883 symbol_id: 0xa1f151cb + symbol_id: 0xba7da88a symbol_id: 0x10425c32 symbol_id: 0xbd9a7739 symbol_id: 0x82c387e4 @@ -411037,6 +411961,7 @@ interface { symbol_id: 0xd1252dfa symbol_id: 0xf3c9734f symbol_id: 0x6c9a6915 + symbol_id: 0x43a4025b symbol_id: 0x0dd13028 symbol_id: 0xfc46114a symbol_id: 0x5dc64161 @@ -415231,6 +416156,7 @@ interface { symbol_id: 0xfccd15d1 symbol_id: 0x591431f1 symbol_id: 0x6869c83d + symbol_id: 0xa8f0fe44 symbol_id: 0x7cfd9233 symbol_id: 0xbd25c7d0 symbol_id: 0x5bbd3545 @@ -415614,6 +416540,7 @@ interface { symbol_id: 0x7da4e281 symbol_id: 0x811fc2f9 symbol_id: 0xaff7b9fa + symbol_id: 0x406267f4 symbol_id: 0x73c499cf symbol_id: 0x1e897b44 symbol_id: 0xdc4939d2 @@ -415645,6 +416572,7 @@ interface { symbol_id: 0x201afca9 symbol_id: 0x3be9765e symbol_id: 0xd75ad246 + symbol_id: 0xeedbb4b8 symbol_id: 0xdefa9d60 symbol_id: 0x905187d4 symbol_id: 0x8483fc3d @@ -415750,6 +416678,7 @@ interface { symbol_id: 0x58937c87 symbol_id: 0xe3f9d54d symbol_id: 0xd80a0cec + symbol_id: 0x80c1324b symbol_id: 0xb61e8892 symbol_id: 0xd5bd73b9 symbol_id: 0x951bfee9 diff --git a/android/abi_gki_aarch64_db845c b/android/abi_gki_aarch64_db845c index 14c68b6f1401..98bc19a295e4 100644 --- a/android/abi_gki_aarch64_db845c +++ b/android/abi_gki_aarch64_db845c @@ -865,6 +865,7 @@ device_get_dma_attr device_match_fwnode devm_krealloc + devm_tegra_memory_controller_get driver_find_device generic_device_group iommu_alloc_resv_region @@ -881,6 +882,7 @@ pci_device_group platform_irq_count report_iommu_fault + tegra_mc_probe_device # required by ath10k_core.ko cpu_latency_qos_add_request diff --git a/android/abi_gki_aarch64_pixel b/android/abi_gki_aarch64_pixel index 0d1b0c47954a..3606c97de5ff 100644 --- a/android/abi_gki_aarch64_pixel +++ b/android/abi_gki_aarch64_pixel @@ -82,6 +82,7 @@ __bitmap_or bitmap_parse bitmap_parselist + bitmap_parse_user bitmap_print_to_pagebuf __bitmap_set __bitmap_subset diff --git a/android/abi_gki_aarch64_rockchip b/android/abi_gki_aarch64_rockchip index 1679dba4127d..5c3c52b7b61c 100644 --- a/android/abi_gki_aarch64_rockchip +++ b/android/abi_gki_aarch64_rockchip @@ -2995,3 +2995,10 @@ # required by vl6180.ko iio_read_const_attr + +# required by aic_btusb.ko + usb_disable_autosuspend + +# required by wlan_mt7663_usb.ko + usb_anchor_empty + usb_reset_endpoint diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 502f707b59e6..7b4e76e57af5 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -48,6 +48,7 @@ CONFIG_PROFILING=y CONFIG_ARCH_SUNXI=y CONFIG_ARCH_HISI=y CONFIG_ARCH_QCOM=y +CONFIG_ARCH_TEGRA=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=32 CONFIG_PARAVIRT_TIME_ACCOUNTING=y @@ -57,6 +58,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_PMEM=y # CONFIG_ARM64_BTI_KERNEL is not set CONFIG_RANDOMIZE_BASE=y # CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set @@ -399,6 +401,7 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_SAMSUNG=y CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_TEGRA_TCU=y CONFIG_SERIAL_QCOM_GENI=y CONFIG_SERIAL_QCOM_GENI_CONSOLE=y CONFIG_SERIAL_SPRD=y @@ -569,22 +572,22 @@ CONFIG_COMMON_CLK_SCPI=y # CONFIG_SUNXI_CCU is not set CONFIG_HWSPINLOCK=y # CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set -CONFIG_MAILBOX=y CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y CONFIG_REMOTEPROC=y CONFIG_REMOTEPROC_CDEV=y CONFIG_RPMSG_CHAR=y CONFIG_QCOM_GENI_SE=y +CONFIG_ARCH_TEGRA_234_SOC=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y CONFIG_DEVFREQ_GOV_USERSPACE=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_MEMORY=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y CONFIG_IIO_TRIGGER=y CONFIG_PWM=y -CONFIG_GENERIC_PHY=y CONFIG_POWERCAP=y CONFIG_IDLE_INJECT=y CONFIG_ANDROID_BINDER_IPC=y @@ -593,7 +596,6 @@ CONFIG_ANDROID_DEBUG_SYMBOLS=y CONFIG_ANDROID_VENDOR_HOOKS=y CONFIG_ANDROID_DEBUG_KINFO=y CONFIG_LIBNVDIMM=y -CONFIG_INTERCONNECT=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y diff --git a/drivers/amba/Kconfig b/drivers/amba/Kconfig index fb6c7e0b4cce..73f8cd696561 100644 --- a/drivers/amba/Kconfig +++ b/drivers/amba/Kconfig @@ -6,7 +6,6 @@ if ARM_AMBA config TEGRA_AHB bool - default y if ARCH_TEGRA help Adds AHB configuration functionality for NVIDIA Tegra SoCs, which controls AHB bus master arbitration and some performance diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 2e4a51dd55e0..b620c590bed6 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3458,7 +3458,7 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, tr->offsets_size, extra_buffers_size, - !reply && (t->flags & TF_ONE_WAY), current->tgid); + !reply && (t->flags & TF_ONE_WAY)); if (IS_ERR(t->buffer)) { char *s; @@ -5165,6 +5165,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) static void binder_free_proc(struct binder_proc *proc) { + struct binder_proc_wrap *proc_wrap; struct binder_device *device; BUG_ON(!list_empty(&proc->todo)); @@ -5182,7 +5183,8 @@ static void binder_free_proc(struct binder_proc *proc) put_cred(proc->cred); binder_stats_deleted(BINDER_STAT_PROC); trace_android_vh_binder_free_proc(proc); - kfree(proc); + proc_wrap = binder_proc_wrap_entry(proc); + kfree(proc_wrap); } static void binder_free_thread(struct binder_thread *thread) @@ -5888,6 +5890,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) static int binder_open(struct inode *nodp, struct file *filp) { + struct binder_proc_wrap *proc_wrap; struct binder_proc *proc, *itr; struct binder_device *binder_dev; struct binderfs_info *info; @@ -5897,9 +5900,11 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, current->group_leader->pid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); - if (proc == NULL) + proc_wrap = kzalloc(sizeof(*proc_wrap), GFP_KERNEL); + if (proc_wrap == NULL) return -ENOMEM; + proc = &proc_wrap->proc; + spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); @@ -6266,9 +6271,9 @@ static void print_binder_transaction_ilocked(struct seq_file *m, } if (buffer->target_node) seq_printf(m, " node %d", buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd data %pK\n", + seq_printf(m, " size %zd:%zd offset %tx\n", buffer->data_size, buffer->offsets_size, - buffer->user_data); + proc->alloc.buffer - buffer->user_data); } static void print_binder_work_ilocked(struct seq_file *m, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index c7ebf14587a6..6ce5a0264946 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -23,11 +23,11 @@ #include #include #include -#include "binder_alloc.h" +#include "binder_internal.h" #include "binder_trace.h" #include -struct list_lru binder_alloc_lru; +struct list_lru binder_freelist; static DEFINE_MUTEX(binder_alloc_mmap_lock); @@ -126,23 +126,20 @@ static void binder_insert_allocated_buffer_locked( static struct binder_buffer *binder_alloc_prepare_to_free_locked( struct binder_alloc *alloc, - uintptr_t user_ptr) + unsigned long user_ptr) { struct rb_node *n = alloc->allocated_buffers.rb_node; struct binder_buffer *buffer; - void __user *uptr; - - uptr = (void __user *)user_ptr; while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(buffer->free); - if (uptr < buffer->user_data) + if (user_ptr < (uintptr_t)buffer->user_data) { n = n->rb_left; - else if (uptr > buffer->user_data) + } else if (user_ptr > (uintptr_t)buffer->user_data) { n = n->rb_right; - else { + } else { /* * Guard against user threads attempting to * free the buffer when in use by kernel or @@ -169,145 +166,169 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( * Return: Pointer to buffer or NULL */ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, - uintptr_t user_ptr) + unsigned long user_ptr) { struct binder_buffer *buffer; - mutex_lock(&alloc->mutex); + binder_alloc_lock(alloc); buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr); - mutex_unlock(&alloc->mutex); + binder_alloc_unlock(alloc); return buffer; } -static int binder_update_page_range(struct binder_alloc *alloc, int allocate, - void __user *start, void __user *end) +static inline void +binder_set_installed_page(struct binder_lru_page *lru_page, + struct page *page) +{ + /* Pairs with acquire in binder_get_installed_page() */ + smp_store_release(&lru_page->page_ptr, page); +} + +static inline struct page * +binder_get_installed_page(struct binder_lru_page *lru_page) +{ + /* Pairs with release in binder_set_installed_page() */ + return smp_load_acquire(&lru_page->page_ptr); +} + +static void binder_lru_freelist_add(struct binder_alloc *alloc, + unsigned long start, unsigned long end) { - void __user *page_addr; - unsigned long user_page_addr; struct binder_lru_page *page; - struct vm_area_struct *vma = NULL; - struct mm_struct *mm = NULL; - bool need_mm = false; + unsigned long page_addr; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %pK-%pK\n", alloc->pid, - allocate ? "allocate" : "free", start, end); - - if (end <= start) - return 0; - - trace_binder_update_page_range(alloc, allocate, start, end); - - if (allocate == 0) - goto free_range; + trace_binder_update_page_range(alloc, false, start, end); for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; - if (!page->page_ptr) { - need_mm = true; - break; - } - } - - if (need_mm && mmget_not_zero(alloc->mm)) - mm = alloc->mm; - - if (mm) { - mmap_write_lock(mm); - vma = alloc->vma; - } - - if (!vma && need_mm) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d: binder_alloc_buf failed to map pages in userspace, no vma\n", - alloc->pid); - goto err_no_vma; - } - - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - int ret; - bool on_lru; size_t index; + int ret; - index = (page_addr - alloc->buffer) / PAGE_SIZE; + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; + page = &alloc->pages[index]; + + if (!binder_get_installed_page(page)) + continue; + + trace_binder_free_lru_start(alloc, index); + + ret = list_lru_add(&binder_freelist, &page->lru); + WARN_ON(!ret); + + trace_binder_free_lru_end(alloc, index); + } +} + +static int binder_install_single_page(struct binder_alloc *alloc, + struct binder_lru_page *lru_page, + unsigned long addr) +{ + struct page *page; + int ret = 0; + + if (!mmget_not_zero(alloc->mm)) + return -ESRCH; + + /* + * Protected with mmap_sem in write mode as multiple tasks + * might race to install the same page. + */ + mmap_write_lock(alloc->mm); + if (binder_get_installed_page(lru_page)) + goto out; + + if (!alloc->vma) { + pr_err("%d: %s failed, no vma\n", alloc->pid, __func__); + ret = -ESRCH; + goto out; + } + + page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (!page) { + pr_err("%d: failed to allocate page\n", alloc->pid); + ret = -ENOMEM; + goto out; + } + + ret = vm_insert_page(alloc->vma, addr, page); + if (ret) { + pr_err("%d: %s failed to insert page at offset %lx with %d\n", + alloc->pid, __func__, addr - (uintptr_t)alloc->buffer, + ret); + __free_page(page); + ret = -ENOMEM; + goto out; + } + + /* Mark page installation complete and safe to use */ + binder_set_installed_page(lru_page, page); +out: + mmap_write_unlock(alloc->mm); + mmput_async(alloc->mm); + return ret; +} + +static int binder_install_buffer_pages(struct binder_alloc *alloc, + struct binder_buffer *buffer, + size_t size) +{ + struct binder_lru_page *page; + unsigned long start, final; + unsigned long page_addr; + + start = (uintptr_t)buffer->user_data & PAGE_MASK; + final = PAGE_ALIGN((uintptr_t)buffer->user_data + size); + + for (page_addr = start; page_addr < final; page_addr += PAGE_SIZE) { + unsigned long index; + int ret; + + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; + page = &alloc->pages[index]; + + if (binder_get_installed_page(page)) + continue; + + trace_binder_alloc_page_start(alloc, index); + + ret = binder_install_single_page(alloc, page, page_addr); + if (ret) + return ret; + + trace_binder_alloc_page_end(alloc, index); + } + + return 0; +} + +/* The range of pages should exclude those shared with other buffers */ +static void binder_lru_freelist_del(struct binder_alloc *alloc, + unsigned long start, unsigned long end) +{ + struct binder_lru_page *page; + unsigned long page_addr; + + trace_binder_update_page_range(alloc, true, start, end); + + for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { + unsigned long index; + bool on_lru; + + index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; page = &alloc->pages[index]; if (page->page_ptr) { trace_binder_alloc_lru_start(alloc, index); - on_lru = list_lru_del(&binder_alloc_lru, &page->lru); + on_lru = list_lru_del(&binder_freelist, &page->lru); WARN_ON(!on_lru); trace_binder_alloc_lru_end(alloc, index); continue; } - if (WARN_ON(!vma)) - goto err_page_ptr_cleared; - - trace_binder_alloc_page_start(alloc, index); - page->page_ptr = alloc_page(GFP_KERNEL | - __GFP_HIGHMEM | - __GFP_ZERO); - if (!page->page_ptr) { - pr_err("%d: binder_alloc_buf failed for page at %pK\n", - alloc->pid, page_addr); - goto err_alloc_page_failed; - } - page->alloc = alloc; - INIT_LIST_HEAD(&page->lru); - - user_page_addr = (uintptr_t)page_addr; - ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr); - if (ret) { - pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", - alloc->pid, user_page_addr); - goto err_vm_insert_page_failed; - } - if (index + 1 > alloc->pages_high) alloc->pages_high = index + 1; - - trace_binder_alloc_page_end(alloc, index); } - if (mm) { - mmap_write_unlock(mm); - mmput_async(mm); - } - return 0; - -free_range: - for (page_addr = end - PAGE_SIZE; 1; page_addr -= PAGE_SIZE) { - bool ret; - size_t index; - - index = (page_addr - alloc->buffer) / PAGE_SIZE; - page = &alloc->pages[index]; - - trace_binder_free_lru_start(alloc, index); - - ret = list_lru_add(&binder_alloc_lru, &page->lru); - WARN_ON(!ret); - - trace_binder_free_lru_end(alloc, index); - if (page_addr == start) - break; - continue; - -err_vm_insert_page_failed: - __free_page(page->page_ptr); - page->page_ptr = NULL; -err_alloc_page_failed: -err_page_ptr_cleared: - if (page_addr == start) - break; - } -err_no_vma: - if (mm) { - mmap_write_unlock(mm); - mmput_async(mm); - } - return vma ? -ENOMEM : -ESRCH; } static inline void binder_alloc_set_vma(struct binder_alloc *alloc, @@ -324,7 +345,44 @@ static inline struct vm_area_struct *binder_alloc_get_vma( return smp_load_acquire(&alloc->vma); } -static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) +static void debug_no_space_locked(struct binder_alloc *alloc) +{ + size_t largest_alloc_size = 0; + struct binder_buffer *buffer; + size_t allocated_buffers = 0; + size_t largest_free_size = 0; + size_t total_alloc_size = 0; + size_t total_free_size = 0; + size_t free_buffers = 0; + size_t buffer_size; + struct rb_node *n; + + for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + allocated_buffers++; + total_alloc_size += buffer_size; + if (buffer_size > largest_alloc_size) + largest_alloc_size = buffer_size; + } + + for (n = rb_first(&alloc->free_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + free_buffers++; + total_free_size += buffer_size; + if (buffer_size > largest_free_size) + largest_free_size = buffer_size; + } + + binder_alloc_debug(BINDER_DEBUG_USER_ERROR, + "allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n", + total_alloc_size, allocated_buffers, + largest_alloc_size, total_free_size, + free_buffers, largest_free_size); +} + +static bool debug_low_async_space_locked(struct binder_alloc *alloc) { /* * Find the amount and size of buffers allocated by the current caller; @@ -333,10 +391,20 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) * and at some point we'll catch them in the act. This is more efficient * than keeping a map per pid. */ - struct rb_node *n; struct binder_buffer *buffer; size_t total_alloc_size = 0; + int pid = current->tgid; size_t num_buffers = 0; + struct rb_node *n; + + /* + * Only start detecting spammers once we have less than 20% of async + * space left (which is less than 10% of total buffer size). + */ + if (alloc->free_async_space >= alloc->buffer_size / 10) { + alloc->oneway_spam_detected = false; + return false; + } for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) { @@ -366,67 +434,38 @@ static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) return false; } +/* Callers preallocate @new_buffer, it is freed by this function if unused */ static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async, - int pid) + struct binder_buffer *new_buffer, + size_t size, + int is_async) { struct rb_node *n = alloc->free_buffers.rb_node; - struct binder_buffer *buffer; - size_t buffer_size; struct rb_node *best_fit = NULL; - void __user *has_page_addr; - void __user *end_page_addr; - size_t size, data_offsets_size; - int ret; - bool should_fail = false; - - /* Check binder_alloc is fully initialized */ - if (!binder_alloc_get_vma(alloc)) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d: binder_alloc_buf, no vma\n", - alloc->pid); - return ERR_PTR(-ESRCH); - } - - data_offsets_size = ALIGN(data_size, sizeof(void *)) + - ALIGN(offsets_size, sizeof(void *)); - - if (data_offsets_size < data_size || data_offsets_size < offsets_size) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid size %zd-%zd\n", - alloc->pid, data_size, offsets_size); - return ERR_PTR(-EINVAL); - } - size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); - if (size < data_offsets_size || size < extra_buffers_size) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid extra_buffers_size %zd\n", - alloc->pid, extra_buffers_size); - return ERR_PTR(-EINVAL); - } + struct binder_buffer *buffer; + unsigned long next_used_page; + unsigned long curr_last_page; + bool should_fail = false; + size_t buffer_size; trace_android_vh_binder_alloc_new_buf_locked(size, &alloc->free_async_space, is_async); - trace_android_vh_binder_detect_low_async_space(is_async, &alloc->free_async_space, pid, - &should_fail); + trace_android_vh_binder_detect_low_async_space(is_async, &alloc->free_async_space, + current->tgid, &should_fail); if (should_fail) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, not allowed to alloc more async space\n", alloc->pid, size); - return ERR_PTR(-EPERM); + buffer = ERR_PTR(-EPERM); + goto out; } - /* Pad 0-size buffers so they get assigned unique addresses */ - size = max(size, sizeof(void *)); - if (is_async && alloc->free_async_space < size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", alloc->pid, size); - return ERR_PTR(-ENOSPC); + buffer = ERR_PTR(-ENOSPC); + goto out; } while (n) { @@ -437,121 +476,92 @@ static struct binder_buffer *binder_alloc_new_buf_locked( if (size < buffer_size) { best_fit = n; n = n->rb_left; - } else if (size > buffer_size) + } else if (size > buffer_size) { n = n->rb_right; - else { + } else { best_fit = n; break; } } - if (best_fit == NULL) { - size_t allocated_buffers = 0; - size_t largest_alloc_size = 0; - size_t total_alloc_size = 0; - size_t free_buffers = 0; - size_t largest_free_size = 0; - size_t total_free_size = 0; - for (n = rb_first(&alloc->allocated_buffers); n != NULL; - n = rb_next(n)) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - allocated_buffers++; - total_alloc_size += buffer_size; - if (buffer_size > largest_alloc_size) - largest_alloc_size = buffer_size; - } - for (n = rb_first(&alloc->free_buffers); n != NULL; - n = rb_next(n)) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - free_buffers++; - total_free_size += buffer_size; - if (buffer_size > largest_free_size) - largest_free_size = buffer_size; - } + if (unlikely(!best_fit)) { binder_alloc_debug(BINDER_DEBUG_USER_ERROR, "%d: binder_alloc_buf size %zd failed, no address space\n", alloc->pid, size); - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n", - total_alloc_size, allocated_buffers, - largest_alloc_size, total_free_size, - free_buffers, largest_free_size); - return ERR_PTR(-ENOSPC); + debug_no_space_locked(alloc); + buffer = ERR_PTR(-ENOSPC); + goto out; } - if (n == NULL) { + + if (buffer_size != size) { + /* Found an oversized buffer and needs to be split */ buffer = rb_entry(best_fit, struct binder_buffer, rb_node); buffer_size = binder_alloc_buffer_size(alloc, buffer); + + WARN_ON(n || buffer_size == size); + new_buffer->user_data = buffer->user_data + size; + list_add(&new_buffer->entry, &buffer->entry); + new_buffer->free = 1; + binder_insert_free_buffer(alloc, new_buffer); + new_buffer = NULL; } binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", alloc->pid, size, buffer, buffer_size); - has_page_addr = (void __user *) - (((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK); - WARN_ON(n && buffer_size != size); - end_page_addr = - (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size); - if (end_page_addr > has_page_addr) - end_page_addr = has_page_addr; - ret = binder_update_page_range(alloc, 1, (void __user *) - PAGE_ALIGN((uintptr_t)buffer->user_data), end_page_addr); - if (ret) - return ERR_PTR(ret); + /* + * Now we remove the pages from the freelist. A clever calculation + * with buffer_size determines if the last page is shared with an + * adjacent in-use buffer. In such case, the page has been already + * removed from the freelist so we trim our range short. + */ + next_used_page = ((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK; + curr_last_page = PAGE_ALIGN((uintptr_t)buffer->user_data + size); + binder_lru_freelist_del(alloc, PAGE_ALIGN((uintptr_t)buffer->user_data), + min(next_used_page, curr_last_page)); - if (buffer_size != size) { - struct binder_buffer *new_buffer; - - new_buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!new_buffer) { - pr_err("%s: %d failed to alloc new buffer struct\n", - __func__, alloc->pid); - goto err_alloc_buf_struct_failed; - } - new_buffer->user_data = (u8 __user *)buffer->user_data + size; - list_add(&new_buffer->entry, &buffer->entry); - new_buffer->free = 1; - binder_insert_free_buffer(alloc, new_buffer); - } - - rb_erase(best_fit, &alloc->free_buffers); + rb_erase(&buffer->rb_node, &alloc->free_buffers); buffer->free = 0; buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got %pK\n", - alloc->pid, size, buffer); - buffer->data_size = data_size; - buffer->offsets_size = offsets_size; buffer->async_transaction = is_async; - buffer->extra_buffers_size = extra_buffers_size; - buffer->pid = pid; buffer->oneway_spam_suspect = false; if (is_async) { alloc->free_async_space -= size; binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_alloc_buf size %zd async free %zd\n", alloc->pid, size, alloc->free_async_space); - if (alloc->free_async_space < alloc->buffer_size / 10) { - /* - * Start detecting spammers once we have less than 20% - * of async space left (which is less than 10% of total - * buffer size). - */ - buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc, pid); - } else { - alloc->oneway_spam_detected = false; - } + if (debug_low_async_space_locked(alloc)) + buffer->oneway_spam_suspect = true; } - return buffer; -err_alloc_buf_struct_failed: - binder_update_page_range(alloc, 0, (void __user *) - PAGE_ALIGN((uintptr_t)buffer->user_data), - end_page_addr); - return ERR_PTR(-ENOMEM); +out: + /* Discard possibly unused new_buffer */ + kfree(new_buffer); + return buffer; +} + +/* Calculate the sanitized total size, returns 0 for invalid request */ +static inline size_t sanitized_size(size_t data_size, + size_t offsets_size, + size_t extra_buffers_size) +{ + size_t total, tmp; + + /* Align to pointer size and check for overflows */ + tmp = ALIGN(data_size, sizeof(void *)) + + ALIGN(offsets_size, sizeof(void *)); + if (tmp < data_size || tmp < offsets_size) + return 0; + total = tmp + ALIGN(extra_buffers_size, sizeof(void *)); + if (total < tmp || total < extra_buffers_size) + return 0; + + /* Pad 0-sized buffers so they get a unique address */ + total = max(total, sizeof(void *)); + + return total; } /** @@ -561,7 +571,6 @@ err_alloc_buf_struct_failed: * @offsets_size: user specified buffer offset * @extra_buffers_size: size of extra space for meta-data (eg, security context) * @is_async: buffer for async transaction - * @pid: pid to attribute allocation to (used for debugging) * * Allocate a new buffer given the requested sizes. Returns * the kernel version of the buffer pointer. The size allocated @@ -574,74 +583,89 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, size_t data_size, size_t offsets_size, size_t extra_buffers_size, - int is_async, - int pid) + int is_async) { - struct binder_buffer *buffer; + struct binder_buffer *buffer, *next; + size_t size; + int ret; - mutex_lock(&alloc->mutex); - buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size, - extra_buffers_size, is_async, pid); - mutex_unlock(&alloc->mutex); + /* Check binder_alloc is fully initialized */ + if (!binder_alloc_get_vma(alloc)) { + binder_alloc_debug(BINDER_DEBUG_USER_ERROR, + "%d: binder_alloc_buf, no vma\n", + alloc->pid); + return ERR_PTR(-ESRCH); + } + + size = sanitized_size(data_size, offsets_size, extra_buffers_size); + if (unlikely(!size)) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid size %zd-%zd-%zd\n", + alloc->pid, data_size, offsets_size, + extra_buffers_size); + return ERR_PTR(-EINVAL); + } + + /* Preallocate the next buffer */ + next = kzalloc(sizeof(*next), GFP_KERNEL); + if (!next) + return ERR_PTR(-ENOMEM); + + binder_alloc_lock(alloc); + buffer = binder_alloc_new_buf_locked(alloc, next, size, is_async); + if (IS_ERR(buffer)) { + binder_alloc_unlock(alloc); + goto out; + } + + buffer->data_size = data_size; + buffer->offsets_size = offsets_size; + buffer->extra_buffers_size = extra_buffers_size; + buffer->pid = current->tgid; + binder_alloc_unlock(alloc); + + ret = binder_install_buffer_pages(alloc, buffer, size); + if (ret) { + binder_alloc_free_buf(alloc, buffer); + buffer = ERR_PTR(ret); + } +out: return buffer; } -static void __user *buffer_start_page(struct binder_buffer *buffer) +static unsigned long buffer_start_page(struct binder_buffer *buffer) { - return (void __user *)((uintptr_t)buffer->user_data & PAGE_MASK); + return (uintptr_t)buffer->user_data & PAGE_MASK; } -static void __user *prev_buffer_end_page(struct binder_buffer *buffer) +static unsigned long prev_buffer_end_page(struct binder_buffer *buffer) { - return (void __user *) - (((uintptr_t)(buffer->user_data) - 1) & PAGE_MASK); + return ((uintptr_t)buffer->user_data - 1) & PAGE_MASK; } static void binder_delete_free_buffer(struct binder_alloc *alloc, struct binder_buffer *buffer) { - struct binder_buffer *prev, *next = NULL; - bool to_free = true; + struct binder_buffer *prev, *next; + + if (PAGE_ALIGNED(buffer->user_data)) + goto skip_freelist; BUG_ON(alloc->buffers.next == &buffer->entry); prev = binder_buffer_prev(buffer); BUG_ON(!prev->free); - if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) { - to_free = false; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", - alloc->pid, buffer->user_data, - prev->user_data); - } + if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) + goto skip_freelist; if (!list_is_last(&buffer->entry, &alloc->buffers)) { next = binder_buffer_next(buffer); - if (buffer_start_page(next) == buffer_start_page(buffer)) { - to_free = false; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", - alloc->pid, - buffer->user_data, - next->user_data); - } + if (buffer_start_page(next) == buffer_start_page(buffer)) + goto skip_freelist; } - if (PAGE_ALIGNED(buffer->user_data)) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer start %pK is page aligned\n", - alloc->pid, buffer->user_data); - to_free = false; - } - - if (to_free) { - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK do not share page with %pK or %pK\n", - alloc->pid, buffer->user_data, - prev->user_data, - next ? next->user_data : NULL); - binder_update_page_range(alloc, 0, buffer_start_page(buffer), - buffer_start_page(buffer) + PAGE_SIZE); - } + binder_lru_freelist_add(alloc, buffer_start_page(buffer), + buffer_start_page(buffer) + PAGE_SIZE); +skip_freelist: list_del(&buffer->entry); kfree(buffer); } @@ -674,10 +698,8 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, alloc->pid, size, alloc->free_async_space); } - binder_update_page_range(alloc, 0, - (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data), - (void __user *)(((uintptr_t) - buffer->user_data + buffer_size) & PAGE_MASK)); + binder_lru_freelist_add(alloc, PAGE_ALIGN((uintptr_t)buffer->user_data), + ((uintptr_t)buffer->user_data + buffer_size) & PAGE_MASK); rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; @@ -701,444 +723,6 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, binder_insert_free_buffer(alloc, buffer); } -static void binder_alloc_clear_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer); -/** - * binder_alloc_free_buf() - free a binder buffer - * @alloc: binder_alloc for this proc - * @buffer: kernel pointer to buffer - * - * Free the buffer allocated via binder_alloc_new_buf() - */ -void binder_alloc_free_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - /* - * We could eliminate the call to binder_alloc_clear_buf() - * from binder_alloc_deferred_release() by moving this to - * binder_free_buf_locked(). However, that could - * increase contention for the alloc mutex if clear_on_free - * is used frequently for large buffers. The mutex is not - * needed for correctness here. - */ - if (buffer->clear_on_free) { - binder_alloc_clear_buf(alloc, buffer); - buffer->clear_on_free = false; - } - mutex_lock(&alloc->mutex); - binder_free_buf_locked(alloc, buffer); - mutex_unlock(&alloc->mutex); -} - -/** - * binder_alloc_mmap_handler() - map virtual address space for proc - * @alloc: alloc structure for this proc - * @vma: vma passed to mmap() - * - * Called by binder_mmap() to initialize the space specified in - * vma for allocating binder buffers - * - * Return: - * 0 = success - * -EBUSY = address space already mapped - * -ENOMEM = failed to map memory to given address space - */ -int binder_alloc_mmap_handler(struct binder_alloc *alloc, - struct vm_area_struct *vma) -{ - int ret; - const char *failure_string; - struct binder_buffer *buffer; - - if (unlikely(vma->vm_mm != alloc->mm)) { - ret = -EINVAL; - failure_string = "invalid vma->vm_mm"; - goto err_invalid_mm; - } - - mutex_lock(&binder_alloc_mmap_lock); - if (alloc->buffer_size) { - ret = -EBUSY; - failure_string = "already mapped"; - goto err_already_mapped; - } - alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start, - SZ_4M); - mutex_unlock(&binder_alloc_mmap_lock); - - alloc->buffer = (void __user *)vma->vm_start; - - alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, - sizeof(alloc->pages[0]), - GFP_KERNEL); - if (alloc->pages == NULL) { - ret = -ENOMEM; - failure_string = "alloc page array"; - goto err_alloc_pages_failed; - } - - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - ret = -ENOMEM; - failure_string = "alloc buffer struct"; - goto err_alloc_buf_struct_failed; - } - - buffer->user_data = alloc->buffer; - list_add(&buffer->entry, &alloc->buffers); - buffer->free = 1; - binder_insert_free_buffer(alloc, buffer); - alloc->free_async_space = alloc->buffer_size / 2; - - /* Signal binder_alloc is fully initialized */ - binder_alloc_set_vma(alloc, vma); - - return 0; - -err_alloc_buf_struct_failed: - kfree(alloc->pages); - alloc->pages = NULL; -err_alloc_pages_failed: - alloc->buffer = NULL; - mutex_lock(&binder_alloc_mmap_lock); - alloc->buffer_size = 0; -err_already_mapped: - mutex_unlock(&binder_alloc_mmap_lock); -err_invalid_mm: - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%s: %d %lx-%lx %s failed %d\n", __func__, - alloc->pid, vma->vm_start, vma->vm_end, - failure_string, ret); - return ret; -} - - -void binder_alloc_deferred_release(struct binder_alloc *alloc) -{ - struct rb_node *n; - int buffers, page_count; - struct binder_buffer *buffer; - - buffers = 0; - mutex_lock(&alloc->mutex); - BUG_ON(alloc->vma); - - while ((n = rb_first(&alloc->allocated_buffers))) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - - /* Transaction should already have been freed */ - BUG_ON(buffer->transaction); - - if (buffer->clear_on_free) { - binder_alloc_clear_buf(alloc, buffer); - buffer->clear_on_free = false; - } - binder_free_buf_locked(alloc, buffer); - buffers++; - } - - while (!list_empty(&alloc->buffers)) { - buffer = list_first_entry(&alloc->buffers, - struct binder_buffer, entry); - WARN_ON(!buffer->free); - - list_del(&buffer->entry); - WARN_ON_ONCE(!list_empty(&alloc->buffers)); - kfree(buffer); - } - - page_count = 0; - if (alloc->pages) { - int i; - - for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { - void __user *page_addr; - bool on_lru; - - if (!alloc->pages[i].page_ptr) - continue; - - on_lru = list_lru_del(&binder_alloc_lru, - &alloc->pages[i].lru); - page_addr = alloc->buffer + i * PAGE_SIZE; - binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %pK %s\n", - __func__, alloc->pid, i, page_addr, - on_lru ? "on lru" : "active"); - __free_page(alloc->pages[i].page_ptr); - page_count++; - } - kfree(alloc->pages); - } - mutex_unlock(&alloc->mutex); - if (alloc->mm) - mmdrop(alloc->mm); - - binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, - "%s: %d buffers %d, pages %d\n", - __func__, alloc->pid, buffers, page_count); -} - -static void print_binder_buffer(struct seq_file *m, const char *prefix, - struct binder_buffer *buffer) -{ - seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n", - prefix, buffer->debug_id, buffer->user_data, - buffer->data_size, buffer->offsets_size, - buffer->extra_buffers_size, - buffer->transaction ? "active" : "delivered"); -} - -/** - * binder_alloc_print_allocated() - print buffer info - * @m: seq_file for output via seq_printf() - * @alloc: binder_alloc for this proc - * - * Prints information about every buffer associated with - * the binder_alloc state to the given seq_file - */ -void binder_alloc_print_allocated(struct seq_file *m, - struct binder_alloc *alloc) -{ - struct rb_node *n; - - mutex_lock(&alloc->mutex); - for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) - print_binder_buffer(m, " buffer", - rb_entry(n, struct binder_buffer, rb_node)); - mutex_unlock(&alloc->mutex); -} - -/** - * binder_alloc_print_pages() - print page usage - * @m: seq_file for output via seq_printf() - * @alloc: binder_alloc for this proc - */ -void binder_alloc_print_pages(struct seq_file *m, - struct binder_alloc *alloc) -{ - struct binder_lru_page *page; - int i; - int active = 0; - int lru = 0; - int free = 0; - - mutex_lock(&alloc->mutex); - /* - * Make sure the binder_alloc is fully initialized, otherwise we might - * read inconsistent state. - */ - if (binder_alloc_get_vma(alloc) != NULL) { - for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { - page = &alloc->pages[i]; - if (!page->page_ptr) - free++; - else if (list_empty(&page->lru)) - active++; - else - lru++; - } - } - mutex_unlock(&alloc->mutex); - seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); - seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); -} - -/** - * binder_alloc_get_allocated_count() - return count of buffers - * @alloc: binder_alloc for this proc - * - * Return: count of allocated buffers - */ -int binder_alloc_get_allocated_count(struct binder_alloc *alloc) -{ - struct rb_node *n; - int count = 0; - - mutex_lock(&alloc->mutex); - for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) - count++; - mutex_unlock(&alloc->mutex); - return count; -} - - -/** - * binder_alloc_vma_close() - invalidate address space - * @alloc: binder_alloc for this proc - * - * Called from binder_vma_close() when releasing address space. - * Clears alloc->vma to prevent new incoming transactions from - * allocating more buffers. - */ -void binder_alloc_vma_close(struct binder_alloc *alloc) -{ - binder_alloc_set_vma(alloc, NULL); -} - -/** - * binder_alloc_free_page() - shrinker callback to free pages - * @item: item to free - * @lock: lock protecting the item - * @cb_arg: callback argument - * - * Called from list_lru_walk() in binder_shrink_scan() to free - * up pages when the system is under memory pressure. - */ -enum lru_status binder_alloc_free_page(struct list_head *item, - struct list_lru_one *lru, - spinlock_t *lock, - void *cb_arg) - __must_hold(lock) -{ - struct mm_struct *mm = NULL; - struct binder_lru_page *page = container_of(item, - struct binder_lru_page, - lru); - struct binder_alloc *alloc; - uintptr_t page_addr; - size_t index; - struct vm_area_struct *vma; - - alloc = page->alloc; - if (!mutex_trylock(&alloc->mutex)) - goto err_get_alloc_mutex_failed; - - if (!page->page_ptr) - goto err_page_already_freed; - - index = page - alloc->pages; - page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; - - mm = alloc->mm; - if (!mmget_not_zero(mm)) - goto err_mmget; - if (!mmap_read_trylock(mm)) - goto err_mmap_read_lock_failed; - vma = vma_lookup(mm, page_addr); - if (vma && vma != binder_alloc_get_vma(alloc)) - goto err_invalid_vma; - - list_lru_isolate(lru, item); - spin_unlock(lock); - - if (vma) { - trace_binder_unmap_user_start(alloc, index); - - zap_page_range(vma, page_addr, PAGE_SIZE); - - trace_binder_unmap_user_end(alloc, index); - } - mmap_read_unlock(mm); - mmput_async(mm); - - trace_binder_unmap_kernel_start(alloc, index); - - __free_page(page->page_ptr); - page->page_ptr = NULL; - - trace_binder_unmap_kernel_end(alloc, index); - - spin_lock(lock); - mutex_unlock(&alloc->mutex); - return LRU_REMOVED_RETRY; - -err_invalid_vma: - mmap_read_unlock(mm); -err_mmap_read_lock_failed: - mmput_async(mm); -err_mmget: -err_page_already_freed: - mutex_unlock(&alloc->mutex); -err_get_alloc_mutex_failed: - return LRU_SKIP; -} - -static unsigned long -binder_shrink_count(struct shrinker *shrink, struct shrink_control *sc) -{ - return list_lru_count(&binder_alloc_lru); -} - -static unsigned long -binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) -{ - return list_lru_walk(&binder_alloc_lru, binder_alloc_free_page, - NULL, sc->nr_to_scan); -} - -static struct shrinker binder_shrinker = { - .count_objects = binder_shrink_count, - .scan_objects = binder_shrink_scan, - .seeks = DEFAULT_SEEKS, -}; - -/** - * binder_alloc_init() - called by binder_open() for per-proc initialization - * @alloc: binder_alloc for this proc - * - * Called from binder_open() to initialize binder_alloc fields for - * new binder proc - */ -void binder_alloc_init(struct binder_alloc *alloc) -{ - alloc->pid = current->group_leader->pid; - alloc->mm = current->mm; - mmgrab(alloc->mm); - mutex_init(&alloc->mutex); - INIT_LIST_HEAD(&alloc->buffers); -} - -int binder_alloc_shrinker_init(void) -{ - int ret = list_lru_init(&binder_alloc_lru); - - if (ret == 0) { - ret = register_shrinker(&binder_shrinker, "android-binder"); - if (ret) - list_lru_destroy(&binder_alloc_lru); - } - return ret; -} - -void binder_alloc_shrinker_exit(void) -{ - unregister_shrinker(&binder_shrinker); - list_lru_destroy(&binder_alloc_lru); -} - -/** - * check_buffer() - verify that buffer/offset is safe to access - * @alloc: binder_alloc for this proc - * @buffer: binder buffer to be accessed - * @offset: offset into @buffer data - * @bytes: bytes to access from offset - * - * Check that the @offset/@bytes are within the size of the given - * @buffer and that the buffer is currently active and not freeable. - * Offsets must also be multiples of sizeof(u32). The kernel is - * allowed to touch the buffer in two cases: - * - * 1) when the buffer is being created: - * (buffer->free == 0 && buffer->allow_user_free == 0) - * 2) when the buffer is being torn down: - * (buffer->free == 0 && buffer->transaction == NULL). - * - * Return: true if the buffer is safe to access - */ -static inline bool check_buffer(struct binder_alloc *alloc, - struct binder_buffer *buffer, - binder_size_t offset, size_t bytes) -{ - size_t buffer_size = binder_alloc_buffer_size(alloc, buffer); - - return buffer_size >= bytes && - offset <= buffer_size - bytes && - IS_ALIGNED(offset, sizeof(u32)) && - !buffer->free && - (!buffer->allow_user_free || !buffer->transaction); -} - /** * binder_alloc_get_page() - get kernel pointer for given buffer offset * @alloc: binder_alloc for this proc @@ -1201,6 +785,442 @@ static void binder_alloc_clear_buf(struct binder_alloc *alloc, } } +/** + * binder_alloc_free_buf() - free a binder buffer + * @alloc: binder_alloc for this proc + * @buffer: kernel pointer to buffer + * + * Free the buffer allocated via binder_alloc_new_buf() + */ +void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + /* + * We could eliminate the call to binder_alloc_clear_buf() + * from binder_alloc_deferred_release() by moving this to + * binder_free_buf_locked(). However, that could + * increase contention for the alloc->lock if clear_on_free + * is used frequently for large buffers. This lock is not + * needed for correctness here. + */ + if (buffer->clear_on_free) { + binder_alloc_clear_buf(alloc, buffer); + buffer->clear_on_free = false; + } + binder_alloc_lock(alloc); + binder_free_buf_locked(alloc, buffer); + binder_alloc_unlock(alloc); +} + +/** + * binder_alloc_mmap_handler() - map virtual address space for proc + * @alloc: alloc structure for this proc + * @vma: vma passed to mmap() + * + * Called by binder_mmap() to initialize the space specified in + * vma for allocating binder buffers + * + * Return: + * 0 = success + * -EBUSY = address space already mapped + * -ENOMEM = failed to map memory to given address space + */ +int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma) +{ + struct binder_buffer *buffer; + const char *failure_string; + int ret, i; + + if (unlikely(vma->vm_mm != alloc->mm)) { + ret = -EINVAL; + failure_string = "invalid vma->vm_mm"; + goto err_invalid_mm; + } + + mutex_lock(&binder_alloc_mmap_lock); + if (alloc->buffer_size) { + ret = -EBUSY; + failure_string = "already mapped"; + goto err_already_mapped; + } + alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start, + SZ_4M); + mutex_unlock(&binder_alloc_mmap_lock); + + alloc->buffer = (void __user *)vma->vm_start; + + alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, + sizeof(alloc->pages[0]), + GFP_KERNEL); + if (alloc->pages == NULL) { + ret = -ENOMEM; + failure_string = "alloc page array"; + goto err_alloc_pages_failed; + } + + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + alloc->pages[i].alloc = alloc; + INIT_LIST_HEAD(&alloc->pages[i].lru); + } + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + failure_string = "alloc buffer struct"; + goto err_alloc_buf_struct_failed; + } + + buffer->user_data = alloc->buffer; + list_add(&buffer->entry, &alloc->buffers); + buffer->free = 1; + binder_insert_free_buffer(alloc, buffer); + alloc->free_async_space = alloc->buffer_size / 2; + + /* Signal binder_alloc is fully initialized */ + binder_alloc_set_vma(alloc, vma); + + return 0; + +err_alloc_buf_struct_failed: + kfree(alloc->pages); + alloc->pages = NULL; +err_alloc_pages_failed: + alloc->buffer = 0; + mutex_lock(&binder_alloc_mmap_lock); + alloc->buffer_size = 0; +err_already_mapped: + mutex_unlock(&binder_alloc_mmap_lock); +err_invalid_mm: + binder_alloc_debug(BINDER_DEBUG_USER_ERROR, + "%s: %d %lx-%lx %s failed %d\n", __func__, + alloc->pid, vma->vm_start, vma->vm_end, + failure_string, ret); + return ret; +} + + +void binder_alloc_deferred_release(struct binder_alloc *alloc) +{ + struct rb_node *n; + int buffers, page_count; + struct binder_buffer *buffer; + + buffers = 0; + binder_alloc_lock(alloc); + BUG_ON(alloc->vma); + + while ((n = rb_first(&alloc->allocated_buffers))) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + + /* Transaction should already have been freed */ + BUG_ON(buffer->transaction); + + if (buffer->clear_on_free) { + binder_alloc_clear_buf(alloc, buffer); + buffer->clear_on_free = false; + } + binder_free_buf_locked(alloc, buffer); + buffers++; + } + + while (!list_empty(&alloc->buffers)) { + buffer = list_first_entry(&alloc->buffers, + struct binder_buffer, entry); + WARN_ON(!buffer->free); + + list_del(&buffer->entry); + WARN_ON_ONCE(!list_empty(&alloc->buffers)); + kfree(buffer); + } + + page_count = 0; + if (alloc->pages) { + int i; + + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + unsigned long page_addr; + bool on_lru; + + if (!alloc->pages[i].page_ptr) + continue; + + on_lru = list_lru_del(&binder_freelist, + &alloc->pages[i].lru); + page_addr = (uintptr_t)alloc->buffer + i * PAGE_SIZE; + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%s: %d: page %d %s\n", + __func__, alloc->pid, i, + on_lru ? "on lru" : "active"); + __free_page(alloc->pages[i].page_ptr); + page_count++; + } + kfree(alloc->pages); + } + binder_alloc_unlock(alloc); + if (alloc->mm) + mmdrop(alloc->mm); + + binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, + "%s: %d buffers %d, pages %d\n", + __func__, alloc->pid, buffers, page_count); +} + +/** + * binder_alloc_print_allocated() - print buffer info + * @m: seq_file for output via seq_printf() + * @alloc: binder_alloc for this proc + * + * Prints information about every buffer associated with + * the binder_alloc state to the given seq_file + */ +void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc) +{ + struct binder_buffer *buffer; + struct rb_node *n; + + binder_alloc_lock(alloc); + for (n = rb_first(&alloc->allocated_buffers); n; n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + seq_printf(m, " buffer %d: %tx size %zd:%zd:%zd %s\n", + buffer->debug_id, + buffer->user_data - alloc->buffer, + buffer->data_size, buffer->offsets_size, + buffer->extra_buffers_size, + buffer->transaction ? "active" : "delivered"); + } + binder_alloc_unlock(alloc); +} + +/** + * binder_alloc_print_pages() - print page usage + * @m: seq_file for output via seq_printf() + * @alloc: binder_alloc for this proc + */ +void binder_alloc_print_pages(struct seq_file *m, + struct binder_alloc *alloc) +{ + struct binder_lru_page *page; + int i; + int active = 0; + int lru = 0; + int free = 0; + + binder_alloc_lock(alloc); + /* + * Make sure the binder_alloc is fully initialized, otherwise we might + * read inconsistent state. + */ + if (binder_alloc_get_vma(alloc) != NULL) { + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + page = &alloc->pages[i]; + if (!page->page_ptr) + free++; + else if (list_empty(&page->lru)) + active++; + else + lru++; + } + } + binder_alloc_unlock(alloc); + seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); + seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); +} + +/** + * binder_alloc_get_allocated_count() - return count of buffers + * @alloc: binder_alloc for this proc + * + * Return: count of allocated buffers + */ +int binder_alloc_get_allocated_count(struct binder_alloc *alloc) +{ + struct rb_node *n; + int count = 0; + + binder_alloc_lock(alloc); + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) + count++; + binder_alloc_unlock(alloc); + return count; +} + + +/** + * binder_alloc_vma_close() - invalidate address space + * @alloc: binder_alloc for this proc + * + * Called from binder_vma_close() when releasing address space. + * Clears alloc->vma to prevent new incoming transactions from + * allocating more buffers. + */ +void binder_alloc_vma_close(struct binder_alloc *alloc) +{ + binder_alloc_set_vma(alloc, NULL); +} + +/** + * binder_alloc_free_page() - shrinker callback to free pages + * @item: item to free + * @lock: lock protecting the item + * @cb_arg: callback argument + * + * Called from list_lru_walk() in binder_shrink_scan() to free + * up pages when the system is under memory pressure. + */ +enum lru_status binder_alloc_free_page(struct list_head *item, + struct list_lru_one *lru, + spinlock_t *lock, + void *cb_arg) + __must_hold(lock) +{ + struct binder_lru_page *page = container_of(item, typeof(*page), lru); + struct binder_alloc *alloc = page->alloc; + struct mm_struct *mm = alloc->mm; + struct vm_area_struct *vma; + struct page *page_to_free; + unsigned long page_addr; + size_t index; + + if (!mmget_not_zero(mm)) + goto err_mmget; + if (!mmap_read_trylock(mm)) + goto err_mmap_read_lock_failed; + if (!binder_alloc_trylock(alloc)) + goto err_get_alloc_lock_failed; + if (!page->page_ptr) + goto err_page_already_freed; + + index = page - alloc->pages; + page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; + + vma = vma_lookup(mm, page_addr); + if (vma && vma != binder_alloc_get_vma(alloc)) + goto err_invalid_vma; + + trace_binder_unmap_kernel_start(alloc, index); + + page_to_free = page->page_ptr; + page->page_ptr = NULL; + + trace_binder_unmap_kernel_end(alloc, index); + + list_lru_isolate(lru, item); + binder_alloc_unlock(alloc); + spin_unlock(lock); + + if (vma) { + trace_binder_unmap_user_start(alloc, index); + + zap_page_range(vma, page_addr, PAGE_SIZE); + + trace_binder_unmap_user_end(alloc, index); + } + + mmap_read_unlock(mm); + mmput_async(mm); + __free_page(page_to_free); + + spin_lock(lock); + return LRU_REMOVED_RETRY; + +err_invalid_vma: +err_page_already_freed: + binder_alloc_unlock(alloc); +err_get_alloc_lock_failed: + mmap_read_unlock(mm); +err_mmap_read_lock_failed: + mmput_async(mm); +err_mmget: + return LRU_SKIP; +} + +static unsigned long +binder_shrink_count(struct shrinker *shrink, struct shrink_control *sc) +{ + return list_lru_count(&binder_freelist); +} + +static unsigned long +binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) +{ + return list_lru_walk(&binder_freelist, binder_alloc_free_page, + NULL, sc->nr_to_scan); +} + +static struct shrinker binder_shrinker = { + .count_objects = binder_shrink_count, + .scan_objects = binder_shrink_scan, + .seeks = DEFAULT_SEEKS, +}; + +/** + * binder_alloc_init() - called by binder_open() for per-proc initialization + * @alloc: binder_alloc for this proc + * + * Called from binder_open() to initialize binder_alloc fields for + * new binder proc + */ +void binder_alloc_init(struct binder_alloc *alloc) +{ + alloc->pid = current->group_leader->pid; + alloc->mm = current->mm; + mmgrab(alloc->mm); + binder_alloc_lock_init(alloc); + INIT_LIST_HEAD(&alloc->buffers); +} + +int binder_alloc_shrinker_init(void) +{ + int ret = list_lru_init(&binder_freelist); + + if (ret == 0) { + ret = register_shrinker(&binder_shrinker, "android-binder"); + if (ret) + list_lru_destroy(&binder_freelist); + } + return ret; +} + +void binder_alloc_shrinker_exit(void) +{ + unregister_shrinker(&binder_shrinker); + list_lru_destroy(&binder_freelist); +} + +/** + * check_buffer() - verify that buffer/offset is safe to access + * @alloc: binder_alloc for this proc + * @buffer: binder buffer to be accessed + * @offset: offset into @buffer data + * @bytes: bytes to access from offset + * + * Check that the @offset/@bytes are within the size of the given + * @buffer and that the buffer is currently active and not freeable. + * Offsets must also be multiples of sizeof(u32). The kernel is + * allowed to touch the buffer in two cases: + * + * 1) when the buffer is being created: + * (buffer->free == 0 && buffer->allow_user_free == 0) + * 2) when the buffer is being torn down: + * (buffer->free == 0 && buffer->transaction == NULL). + * + * Return: true if the buffer is safe to access + */ +static inline bool check_buffer(struct binder_alloc *alloc, + struct binder_buffer *buffer, + binder_size_t offset, size_t bytes) +{ + size_t buffer_size = binder_alloc_buffer_size(alloc, buffer); + + return buffer_size >= bytes && + offset <= buffer_size - bytes && + IS_ALIGNED(offset, sizeof(u32)) && + !buffer->free && + (!buffer->allow_user_free || !buffer->transaction); +} + /** * binder_alloc_copy_user_to_buffer() - copy src user to tgt user * @alloc: binder_alloc for this proc diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index dc1e2b01dd64..d3ac713744b0 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -15,7 +15,7 @@ #include #include -extern struct list_lru binder_alloc_lru; +extern struct list_lru binder_freelist; struct binder_transaction; /** @@ -49,21 +49,19 @@ struct binder_buffer { unsigned async_transaction:1; unsigned oneway_spam_suspect:1; unsigned debug_id:27; - struct binder_transaction *transaction; - struct binder_node *target_node; size_t data_size; size_t offsets_size; size_t extra_buffers_size; void __user *user_data; - int pid; + int pid; }; /** * struct binder_lru_page - page object used for binder shrinker * @page_ptr: pointer to physical page in mmap'd space - * @lru: entry in binder_alloc_lru + * @lru: entry in binder_freelist * @alloc: binder_alloc for a proc */ struct binder_lru_page { @@ -74,7 +72,7 @@ struct binder_lru_page { /** * struct binder_alloc - per-binder proc state for binder allocator - * @mutex: protects binder_alloc fields + * @lock: protects binder_alloc fields * @vma: vm_area_struct passed to mmap_handler * (invariant after mmap) * @mm: copy of task->mm (invariant after open) @@ -121,47 +119,29 @@ static inline void binder_selftest_alloc(struct binder_alloc *alloc) {} enum lru_status binder_alloc_free_page(struct list_head *item, struct list_lru_one *lru, spinlock_t *lock, void *cb_arg); -extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async, - int pid); -extern void binder_alloc_init(struct binder_alloc *alloc); -extern int binder_alloc_shrinker_init(void); -extern void binder_alloc_shrinker_exit(void); -extern void binder_alloc_vma_close(struct binder_alloc *alloc); -extern struct binder_buffer * +struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async); +void binder_alloc_init(struct binder_alloc *alloc); +int binder_alloc_shrinker_init(void); +void binder_alloc_shrinker_exit(void); +void binder_alloc_vma_close(struct binder_alloc *alloc); +struct binder_buffer * binder_alloc_prepare_to_free(struct binder_alloc *alloc, - uintptr_t user_ptr); -extern void binder_alloc_free_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer); -extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, - struct vm_area_struct *vma); -extern void binder_alloc_deferred_release(struct binder_alloc *alloc); -extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc); -extern void binder_alloc_print_allocated(struct seq_file *m, - struct binder_alloc *alloc); + unsigned long user_ptr); +void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer); +int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma); +void binder_alloc_deferred_release(struct binder_alloc *alloc); +int binder_alloc_get_allocated_count(struct binder_alloc *alloc); +void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc); void binder_alloc_print_pages(struct seq_file *m, struct binder_alloc *alloc); -/** - * binder_alloc_get_free_async_space() - get free space available for async - * @alloc: binder_alloc for this proc - * - * Return: the bytes remaining in the address-space for async transactions - */ -static inline size_t -binder_alloc_get_free_async_space(struct binder_alloc *alloc) -{ - size_t free_async_space; - - mutex_lock(&alloc->mutex); - free_async_space = alloc->free_async_space; - mutex_unlock(&alloc->mutex); - return free_async_space; -} - unsigned long binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc, struct binder_buffer *buffer, diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index c2b323bc3b3a..f01de0af2a2e 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -93,14 +93,14 @@ static bool check_buffer_pages_allocated(struct binder_alloc *alloc, struct binder_buffer *buffer, size_t size) { - void __user *page_addr; - void __user *end; + unsigned long page_addr; + unsigned long end; int page_index; - end = (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size); - page_addr = buffer->user_data; + end = PAGE_ALIGN((uintptr_t)buffer->user_data + size); + page_addr = (uintptr_t)buffer->user_data; for (; page_addr < end; page_addr += PAGE_SIZE) { - page_index = (page_addr - alloc->buffer) / PAGE_SIZE; + page_index = (page_addr - (uintptr_t)alloc->buffer) / PAGE_SIZE; if (!alloc->pages[page_index].page_ptr || !list_empty(&alloc->pages[page_index].lru)) { pr_err("expect alloc but is %s at page index %d\n", @@ -119,7 +119,7 @@ static void binder_selftest_alloc_buf(struct binder_alloc *alloc, int i; for (i = 0; i < BUFFER_NUM; i++) { - buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0, 0); + buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0); if (IS_ERR(buffers[i]) || !check_buffer_pages_allocated(alloc, buffers[i], sizes[i])) { @@ -158,8 +158,8 @@ static void binder_selftest_free_page(struct binder_alloc *alloc) int i; unsigned long count; - while ((count = list_lru_count(&binder_alloc_lru))) { - list_lru_walk(&binder_alloc_lru, binder_alloc_free_page, + while ((count = list_lru_count(&binder_freelist))) { + list_lru_walk(&binder_freelist, binder_alloc_free_page, NULL, count); } @@ -183,7 +183,7 @@ static void binder_selftest_alloc_free(struct binder_alloc *alloc, /* Allocate from lru. */ binder_selftest_alloc_buf(alloc, buffers, sizes, seq); - if (list_lru_count(&binder_alloc_lru)) + if (list_lru_count(&binder_freelist)) pr_err("lru list should be empty but is not\n"); binder_selftest_free_buf(alloc, buffers, sizes, seq, end); diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 439c8c2403c3..4164c346b301 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -461,6 +461,66 @@ struct binder_proc { bool oneway_spam_detection_enabled; }; +struct binder_proc_wrap { + struct binder_proc proc; + spinlock_t lock; +}; + +static inline struct binder_proc * +binder_proc_entry(struct binder_alloc *alloc) +{ + return container_of(alloc, struct binder_proc, alloc); +} + +static inline struct binder_proc_wrap * +binder_proc_wrap_entry(struct binder_proc *proc) +{ + return container_of(proc, struct binder_proc_wrap, proc); +} + +static inline struct binder_proc_wrap * +binder_alloc_to_proc_wrap(struct binder_alloc *alloc) +{ + return binder_proc_wrap_entry(binder_proc_entry(alloc)); +} + +static inline void binder_alloc_lock_init(struct binder_alloc *alloc) +{ + spin_lock_init(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline void binder_alloc_lock(struct binder_alloc *alloc) +{ + spin_lock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline void binder_alloc_unlock(struct binder_alloc *alloc) +{ + spin_unlock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +static inline int binder_alloc_trylock(struct binder_alloc *alloc) +{ + return spin_trylock(&binder_alloc_to_proc_wrap(alloc)->lock); +} + +/** + * binder_alloc_get_free_async_space() - get free space available for async + * @alloc: binder_alloc for this proc + * + * Return: the bytes remaining in the address-space for async transactions + */ +static inline size_t +binder_alloc_get_free_async_space(struct binder_alloc *alloc) +{ + size_t free_async_space; + + binder_alloc_lock(alloc); + free_async_space = alloc->free_async_space; + binder_alloc_unlock(alloc); + return free_async_space; +} + /** * struct binder_thread - binder thread bookkeeping * @proc: binder process for this thread diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index 5d82cf8af88b..618c4cc016c5 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -341,7 +341,7 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release, TRACE_EVENT(binder_update_page_range, TP_PROTO(struct binder_alloc *alloc, bool allocate, - void __user *start, void __user *end), + unsigned long start, unsigned long end), TP_ARGS(alloc, allocate, start, end), TP_STRUCT__entry( __field(int, proc) @@ -352,7 +352,7 @@ TRACE_EVENT(binder_update_page_range, TP_fast_assign( __entry->proc = alloc->pid; __entry->allocate = allocate; - __entry->offset = start - alloc->buffer; + __entry->offset = start - (uintptr_t)alloc->buffer; __entry->size = end - start; ), TP_printk("proc=%d allocate=%d offset=%zu size=%zu", diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 700f71c95495..89e60de76733 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -633,7 +633,6 @@ config GPIO_TB10X config GPIO_TEGRA tristate "NVIDIA Tegra GPIO support" - default ARCH_TEGRA depends on ARCH_TEGRA || COMPILE_TEST depends on OF_GPIO select GPIOLIB_IRQCHIP diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e50f9603d189..9789a3f373f3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1121,7 +1121,6 @@ config I2C_TEGRA config I2C_TEGRA_BPMP tristate "NVIDIA Tegra BPMP I2C controller" depends on TEGRA_BPMP || COMPILE_TEST - default y if TEGRA_BPMP help If you say yes to this option, support will be included for the I2C controller embedded in NVIDIA Tegra SoCs accessed via the BPMP. diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 583a340f9934..7bd40a209e9e 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -522,7 +522,6 @@ config SERIAL_8250_PXA config SERIAL_8250_TEGRA tristate "8250 support for Tegra serial ports" - default SERIAL_8250 depends on SERIAL_8250 depends on ARCH_TEGRA || COMPILE_TEST help diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index a86fe89f5f04..2b0dad42f9af 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1394,8 +1394,16 @@ int usb_add_gadget(struct usb_gadget *gadget) if (ret) goto err_free_id; + ret = sysfs_create_link(&udc->dev.kobj, + &gadget->dev.kobj, "gadget"); + if (ret) + goto err_del_gadget; + return 0; + err_del_gadget: + device_del(&gadget->dev); + err_free_id: ida_free(&gadget_id_numbers, gadget->id_number); @@ -1504,6 +1512,7 @@ void usb_del_gadget(struct usb_gadget *gadget) mutex_unlock(&udc_lock); kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); + sysfs_remove_link(&udc->dev.kobj, "gadget"); flush_work(&gadget->work); device_del(&gadget->dev); ida_free(&gadget_id_numbers, gadget->id_number); diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 34543d2c1f0b..fc89be47a4da 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -5467,6 +5467,7 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port) port->tcpc->set_bist_data(port->tcpc, false); switch (port->state) { + case TOGGLING: case ERROR_RECOVERY: case PORT_RESET: case PORT_RESET_WAIT_OFF: diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6aec06ec2de6..f2c5a2f7fd41 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -878,6 +878,34 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep return res; } +/* + * The ffd.file pointer may be in the process of being torn down due to + * being closed, but we may not have finished eventpoll_release() yet. + * + * Normally, even with the atomic_long_inc_not_zero, the file may have + * been free'd and then gotten re-allocated to something else (since + * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU). + * + * But for epoll, users hold the ep->mtx mutex, and as such any file in + * the process of being free'd will block in eventpoll_release_file() + * and thus the underlying file allocation will not be free'd, and the + * file re-use cannot happen. + * + * For the same reason we can avoid a rcu_read_lock() around the + * operation - 'ffd.file' cannot go away even if the refcount has + * reached zero (but we must still not call out to ->poll() functions + * etc). + */ +static struct file *epi_fget(const struct epitem *epi) +{ + struct file *file; + + file = epi->ffd.file; + if (!atomic_long_inc_not_zero(&file->f_count)) + file = NULL; + return file; +} + /* * Differs from ep_eventpoll_poll() in that internal callers already have * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested() @@ -886,14 +914,22 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep static __poll_t ep_item_poll(const struct epitem *epi, poll_table *pt, int depth) { - struct file *file = epi->ffd.file; + struct file *file = epi_fget(epi); __poll_t res; + /* + * We could return EPOLLERR | EPOLLHUP or something, but let's + * treat this more as "file doesn't exist, poll didn't happen". + */ + if (!file) + return 0; + pt->_key = epi->event.events; if (!is_file_epoll(file)) res = vfs_poll(file, pt); else res = __ep_eventpoll_poll(file, pt, depth); + fput(file); return res & epi->event.events; } diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c index 814d7063581a..eea115de98c7 100644 --- a/fs/incfs/pseudo_files.c +++ b/fs/incfs/pseudo_files.c @@ -1073,7 +1073,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, int rl_size; ssize_t result = 0; bool report_uid; - unsigned long page = 0; + void *page = 0; struct incfs_pending_read_info *reads_buf = NULL; struct incfs_pending_read_info2 *reads_buf2 = NULL; size_t record_size; @@ -1086,13 +1086,13 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, report_uid = mi->mi_options.report_uid; record_size = report_uid ? sizeof(*reads_buf2) : sizeof(*reads_buf); reads_to_collect = len / record_size; - reads_per_page = PAGE_SIZE / record_size; + reads_per_page = INCFS_DATA_FILE_BLOCK_SIZE / record_size; rl_size = READ_ONCE(mi->mi_log.rl_size); if (rl_size == 0) return 0; - page = __get_free_page(GFP_NOFS); + page = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS); if (!page) return -ENOMEM; @@ -1116,7 +1116,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, reads_collected; goto out; } - if (copy_to_user(buf, (void *)page, + if (copy_to_user(buf, page, reads_collected * record_size)) { result = total_reads_collected ? total_reads_collected * record_size : @@ -1133,7 +1133,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, result = total_reads_collected * record_size; *ppos = 0; out: - free_page(page); + kfree(page); return result; } diff --git a/fs/incfs/verity.c b/fs/incfs/verity.c index 562a8e774178..b49441a146d2 100644 --- a/fs/incfs/verity.c +++ b/fs/incfs/verity.c @@ -303,8 +303,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, struct mem_range buf = {.len = INCFS_DATA_FILE_BLOCK_SIZE}; struct mem_range tmp = {.len = 2 * INCFS_DATA_FILE_BLOCK_SIZE}; - buf.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(buf.len)); - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); + buf.data = (u8 *)kzalloc(buf.len, GFP_NOFS); + tmp.data = (u8 *)kzalloc(tmp.len, GFP_NOFS); if (!buf.data || !tmp.data) { error = -ENOMEM; goto out; @@ -372,8 +372,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, } out: - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - free_pages((unsigned long)buf.data, get_order(buf.len)); + kfree(tmp.data); + kfree(buf.data); return error; } diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 0c80779e99e9..7086135a4d7f 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -541,13 +541,15 @@ static int read_folio(struct file *f, struct folio *folio) struct page *page = &folio->page; loff_t offset = 0; loff_t size = 0; - ssize_t bytes_to_read = 0; - ssize_t read_result = 0; + ssize_t total_read = 0; struct data_file *df = get_incfs_data_file(f); int result = 0; void *page_start; int block_index; unsigned int delayed_min_us = 0; + struct mem_range tmp = { + .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE + }; if (!df) { SetPageError(page); @@ -561,32 +563,39 @@ static int read_folio(struct file *f, struct folio *folio) INCFS_DATA_FILE_BLOCK_SIZE; size = df->df_size; - if (offset < size) { - struct mem_range tmp = { - .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE - }; - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); - if (!tmp.data) { - read_result = -ENOMEM; - goto err; - } - bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE); - - read_result = read_single_page_timeouts(df, f, block_index, - range(page_start, bytes_to_read), tmp, - &delayed_min_us); - - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - } else { - bytes_to_read = 0; - read_result = 0; + tmp.data = kzalloc(tmp.len, GFP_NOFS); + if (!tmp.data) { + result = -ENOMEM; + goto err; } + while (offset + total_read < size) { + ssize_t bytes_to_read = min_t(loff_t, + size - offset - total_read, + INCFS_DATA_FILE_BLOCK_SIZE); + + result = read_single_page_timeouts(df, f, block_index, + range(page_start + total_read, bytes_to_read), + tmp, &delayed_min_us); + if (result < 0) + break; + + total_read += result; + block_index++; + + if (result < INCFS_DATA_FILE_BLOCK_SIZE) + break; + if (total_read == PAGE_SIZE) + break; + } + kfree(tmp.data); err: - if (read_result < 0) - result = read_result; - else if (read_result < PAGE_SIZE) - zero_user(page, read_result, PAGE_SIZE - read_result); + if (result < 0) + total_read = 0; + else + result = 0; + if (total_read < PAGE_SIZE) + zero_user(page, total_read, PAGE_SIZE - total_read); if (result == 0) SetPageUptodate(page); @@ -770,8 +779,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) return -EFAULT; usr_fill_block_array = u64_to_user_ptr(fill_blocks.fill_blocks); - data_buf = (u8 *)__get_free_pages(GFP_NOFS | __GFP_COMP, - get_order(data_buf_size)); + data_buf = (u8 *)kzalloc(data_buf_size, GFP_NOFS); if (!data_buf) return -ENOMEM; @@ -806,8 +814,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) break; } - if (data_buf) - free_pages((unsigned long)data_buf, get_order(data_buf_size)); + kfree(data_buf); if (complete) handle_file_completed(f, df); @@ -1807,8 +1814,6 @@ struct dentry *incfs_mount_fs(struct file_system_type *type, int flags, sb->s_blocksize_bits = blksize_bits(sb->s_blocksize); sb->s_xattr = incfs_xattr_ops; - BUILD_BUG_ON(PAGE_SIZE != INCFS_DATA_FILE_BLOCK_SIZE); - if (!dev_name) { pr_err("incfs: Backing dir is not set, filesystem can't be mounted.\n"); error = -ENOENT; diff --git a/include/trace/hooks/binder.h b/include/trace/hooks/binder.h index fa2b762e3401..93641ce4ed6e 100644 --- a/include/trace/hooks/binder.h +++ b/include/trace/hooks/binder.h @@ -82,7 +82,6 @@ DECLARE_HOOK(android_vh_binder_select_special_worklist, DECLARE_HOOK(android_vh_binder_alloc_new_buf_locked, TP_PROTO(size_t size, size_t *free_async_space, int is_async), TP_ARGS(size, free_async_space, is_async)); - DECLARE_HOOK(android_vh_binder_detect_low_async_space, TP_PROTO(int is_async, size_t *free_async_space, int pid, bool *should_fail), TP_ARGS(is_async, free_async_space, pid, should_fail)); diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index bb8945ca53cd..25f958ffa37f 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -85,7 +85,7 @@ find $cpio_dir -type f -print0 | # pre-sorted, as --sort=name might not be available. find $cpio_dir -printf "./%P\n" | LC_ALL=C sort | \ tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ - --owner=0 --group=0 --numeric-owner --no-recursion \ + --owner=0 --group=0 --numeric-owner --no-recursion --mode=u=rw,go=r,a+X \ -I $XZ -cf $tarfile -C $cpio_dir/ -T - > /dev/null echo $headers_md5 > kernel/kheaders.md5 diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index 6b5c1175faea..ef66cce84d61 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -311,7 +311,7 @@ config UNUSED_KSYMS_WHITELIST exported at all times, even in absence of in-tree users. The value to set here is the path to a text file containing the list of symbols, one per line. The path can be absolute, or relative to the kernel - source tree. + source or obj tree. config MODULES_TREE_LOOKUP def_bool y diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 653fadbad302..e12178d677e2 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -31,7 +31,7 @@ fi ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) if [ -n "$ksym_wl" ]; then - [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" + [ "${ksym_wl}" != "${ksym_wl#/}" ] || [ -f "$ksym_wl" ] || ksym_wl="$abs_srctree/$ksym_wl" if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh index 728d55190d97..746e91c86860 100755 --- a/scripts/pahole-flags.sh +++ b/scripts/pahole-flags.sh @@ -17,7 +17,7 @@ if [ "${pahole_ver}" -ge "121" ]; then extra_paholeopt="${extra_paholeopt} --btf_gen_floats" fi if [ "${pahole_ver}" -ge "122" ]; then - extra_paholeopt="${extra_paholeopt} -j" + extra_paholeopt="${extra_paholeopt} -j1" fi if [ "${pahole_ver}" -ge "124" ]; then # see PAHOLE_HAS_LANG_EXCLUDE diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index 48b9a803235a..d13ebde20322 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -21,9 +21,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - - - #include #include #include @@ -62,45 +59,47 @@ int clear_time_state(void) #define NUM_FREQ_OUTOFRANGE 4 #define NUM_FREQ_INVALID 2 +#define SHIFTED_PPM (1 << 16) + long valid_freq[NUM_FREQ_VALID] = { - -499<<16, - -450<<16, - -400<<16, - -350<<16, - -300<<16, - -250<<16, - -200<<16, - -150<<16, - -100<<16, - -75<<16, - -50<<16, - -25<<16, - -10<<16, - -5<<16, - -1<<16, + -499 * SHIFTED_PPM, + -450 * SHIFTED_PPM, + -400 * SHIFTED_PPM, + -350 * SHIFTED_PPM, + -300 * SHIFTED_PPM, + -250 * SHIFTED_PPM, + -200 * SHIFTED_PPM, + -150 * SHIFTED_PPM, + -100 * SHIFTED_PPM, + -75 * SHIFTED_PPM, + -50 * SHIFTED_PPM, + -25 * SHIFTED_PPM, + -10 * SHIFTED_PPM, + -5 * SHIFTED_PPM, + -1 * SHIFTED_PPM, -1000, - 1<<16, - 5<<16, - 10<<16, - 25<<16, - 50<<16, - 75<<16, - 100<<16, - 150<<16, - 200<<16, - 250<<16, - 300<<16, - 350<<16, - 400<<16, - 450<<16, - 499<<16, + 1 * SHIFTED_PPM, + 5 * SHIFTED_PPM, + 10 * SHIFTED_PPM, + 25 * SHIFTED_PPM, + 50 * SHIFTED_PPM, + 75 * SHIFTED_PPM, + 100 * SHIFTED_PPM, + 150 * SHIFTED_PPM, + 200 * SHIFTED_PPM, + 250 * SHIFTED_PPM, + 300 * SHIFTED_PPM, + 350 * SHIFTED_PPM, + 400 * SHIFTED_PPM, + 450 * SHIFTED_PPM, + 499 * SHIFTED_PPM, }; long outofrange_freq[NUM_FREQ_OUTOFRANGE] = { - -1000<<16, - -550<<16, - 550<<16, - 1000<<16, + -1000 * SHIFTED_PPM, + -550 * SHIFTED_PPM, + 550 * SHIFTED_PPM, + 1000 * SHIFTED_PPM, }; #define LONG_MAX (~0UL>>1)